1

I'm working on Pintos part 4, specifically indirect blocks for the inode data structure. The block is supposed to have (512 / 4) = 128 integers referring to other disk sectors inside of it. I did a small mock up here in my c program to write mock sectors to a malloc'd mock sector and then read it back. Why are the keys so big? Why isn't it 0, 1, 2, 3, 4.

#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

int main(void) {

  void *mock_sector = malloc(512);
  for (uint32_t i = 0; i < 20; i++) {
    memset(mock_sector + i * sizeof(uint32_t), i, sizeof(uint32_t));
  }

  uint32_t key;
  for (uint32_t i = 0; i < 20; i++) {
    memcpy(&key, mock_sector + i * sizeof(uint32_t), sizeof(uint32_t));
    printf("Key is: %d\n", key);
  }

  return 0;
}

Result ->

Key is: 0
Key is: 16843009
Key is: 33686018
Key is: 50529027
Key is: 67372036
Key is: 84215045
Key is: 101058054
Key is: 117901063
Key is: 134744072
Key is: 151587081
Key is: 168430090
Key is: 185273099
Key is: 202116108
Key is: 218959117
Key is: 235802126
Key is: 252645135
Key is: 269488144
Key is: 286331153
Key is: 303174162
Key is: 320017171

I can even see the addresses I am calling memset on are increasing as they should.

0x18aa010 0x18aa014 0x18aa018 0x18aa01c 0x18aa020 0x18aa024 0x18aa028 0x18aa02c

Nate
  • 81
  • 9

2 Answers2

2

Doing pointer arithmetic by hand, and using memset / memcpy to set and get your values, is insane. The correct way:

((uint32_t *)mock_sector) [i] = i;

And of course malloc (128 * sizeof (uint32_t)), not malloc (512).

gnasher729
  • 51,477
  • 5
  • 75
  • 98
1

If I compile the your program but change the format specifier in printf to be %.8X (base 16) rather than %d (base 10), the output is:

Key is: 00000000
Key is: 01010101
Key is: 02020202
Key is: 03030303
Key is: 04040404
Key is: 05050505
Key is: 06060606
Key is: 07070707
Key is: 08080808
Key is: 09090909
Key is: 0A0A0A0A
Key is: 0B0B0B0B
Key is: 0C0C0C0C
Key is: 0D0D0D0D
Key is: 0E0E0E0E
Key is: 0F0F0F0F
Key is: 10101010
Key is: 11111111
Key is: 12121212
Key is: 13131313

Do you see the pattern and the mistake now?

The second argument to memset is cast to an unsigned char (i.e. a byte) even though it has type int, as documented here. This means that every single byte (not every uint32_t) will get populated with the value of i cast to a byte.

Use this code to write to your array:

memset(mock_sector, 0, 512);

for (uint32_t i = 0; i < 20; i++) 
{
    mock_sector[i * sizeof(uint32_t)] = i;
}
Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • memset(mock_sector + i * sizeof(uint32_t), i, sizeof(uint32_t)); The above answer says im assigning each byte the number to be equal to char of i. I just dont see why. – Nate Nov 20 '18 at 22:50
  • @Nate `memset` is copying `i` to each single byte occupied by the `uint32_t` at the destination address with that 3rd parameter; that's what I'm trying to say. – Govind Parmar Nov 20 '18 at 22:52
  • Got it. But isn't i a 4 byte value (uint32). So its only copying the first byte of i 4 times? – Nate Nov 20 '18 at 22:54