سؤال

I figured out that a constant literal get's placed in the data segment of the program (from SO) and is read-only and hence the line " s[0] = 'a' " would cause an error, which actually did happen when I uncommented that line and ran. However when I looked into the memory window in MS VS, the variables are all placed together in memory. I am curious as to how they(compiler) enforce read-only access to 's'?

#include <iostream>

int main(void)
{
      char *s = "1023";
      char s_arr[] = "4237";
      char *d = "5067";
      char s_arr_1[] = "9999";
      char *e = "6789";
      printf("%c\n", s[0]);
//      s[0] = 'a'; This line would error out since s should point to data segment of the program
      printf("%s\n", s);
      system ("pause");
}

0x002E54F4  31 30 32 33 00 00 00 00 34 32 33 37 00 00 00 00  1023....4237....
0x002E5504  35 30 36 37 00 00 00 00 39 39 39 39 00 00 00 00  5067....9999....
0x002E5514  36 37 38 39 00 00 00 00 25 63 0a 00 25 73 0a 00  6789....%c..%s..
0x002E5524  70 61 75 73 65 00 00 00 00 00 00 00 43 00 3a 00  pause.......C.:.

Edit 1: Updating the value stored in s_arr (which should be placed in stack space) to make it clear that it is placed adjacent to the string constants.

Edit 2: Since I am seeing answers regarding ro/rw access based on pages, Here address .. 0x...4f4 is rw 0x...4fc is ro and again 0x...504 is rw. How do they achieve this granularity? Also since the each page could be a minimum of 4kb, one could argue that the 0x4fb could be the last address of the previous ro page. But I have now added a few more variables to show that they are all placed contiguously in memory and the granularity is per every 8 bytes. You could say, Since pages are at 4k level as you mentioned,

هل كانت مفيدة؟

المحلول

I don't know what made you think that your example shows modifiable memory next to non-modifiable memory. What "granularity" are you talking about? You memory dump does not show anything like that.

The string "4237" that you see in your memory dump is not your s_arr. That "4237" that you see there is a read-only string literal that was used as an initializer for the s_arr. That initializer was copied to s_arr. Meanwhile, the actual s_arr resides somewhere else (in the stack) and is perfectly modifiable. It contains "4237" as well (as its initial value), but that's a completely different "4237", which you don't see in your memory dump. Ask your program to print the address of s_arr and you will see that its is nowhere near the memory range that you dumped.

Again, your claim about "0x...4f4 is rw 0x...4fc is ro and again 0x...504 is rw" is completely incorrect. All these addresses are read-only. None of them are read-write. There no "granularity" there whatsoever.

Remember that a declaration like this

char s_arr[] = "4237";

is really equivalent to

const char *unnamed = "4237";
char s_arr[5];
memcpy(s_arr, unnamed, 5);

In your memory dump, you are looking at that unnamed address from my example above. That memory region is read-only. Your s_arr resides in completely different memory region, which is read-write.

نصائح أخرى

Since 32 bit platforms were introduced, everything is placed into the same segment (This is not exactly so, but it is easier to think that this is so. There are minor caveats that require several pages to explain and they apply to operating system design).

The 32-bit address space is split into several pages. Intell allows to assign RO bits with the page granularity. Debuggers display only the 32-bit (64 bit) address that technically is an offset in the segment. It is fine to call this offset simply address. There will be no mistake in this.

Nevertheless linkers call different memory areas as segments. These segments have nothing to do with Intel memory segments. Linker segments (code, data, stack, etc) are loaded into diffrenet pages. These pages get different attributes (RO/RW, execution permission, etc).

The block of memory you are showing is area where string constants are stored (as you can see all 4 values are directly there one next to another). This area is marked as read-only. On Windows each 4Kb block of memory (page) can have its own attributes (read/write/execute), so even 2 adjascent locations can have different access flags.

The area where variables are is in different location (stack in your case). You can see it by checking value of &s immediate window (or watch window).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top