> *nix константы в readonly памяти держит. > char *ptr = "core dumped."; > *ptr = 'C'; > Эта строка приведет к сегментэйшн фолт.
вот кусок листинга в дебажном режиме
PUBLIC _main
PUBLIC ??_C@_0N@LCLI@core?5dumped?4?$AA@ ; `string'
; COMDAT ??_C@_0N@LCLI@core?5dumped?4?$AA@
; File d:\work\test\test.c
CONST SEGMENT
??_C@_0N@LCLI@core?5dumped?4?$AA@ DB 'core dumped.', 00H ; `string'
CONST ENDS
; COMDAT _main
_TEXT SEGMENT
_ptr$ = -4
_main PROC NEAR ; COMDAT
; 2 : main() {
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 83 ec 44 sub esp, 68 ; 00000044H
00006 53 push ebx
00007 56 push esi
00008 57 push edi
00009 8d 7d bc lea edi, DWORD PTR [ebp-68]
0000c b9 11 00 00 00 mov ecx, 17 ; 00000011H
00011 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH
00016 f3 ab rep stosd
; 3 : char *ptr = "core dumped.";
00018 c7 45 fc 00 00
00 00 mov DWORD PTR _ptr$[ebp], OFFSET FLAT:??_C@_0N@LCLI@core?5dumped?4?$AA@ ; `string'
; 4 : *ptr = 'C';
0001f 8b 45 fc mov eax, DWORD PTR _ptr$[ebp]
00022 c6 00 43 mov BYTE PTR [eax], 67 ; 00000043H
; 5 : }
00025 5f pop edi
00026 5e pop esi
00027 5b pop ebx
00028 8b e5 mov esp, ebp
0002a 5d pop ebp
0002b c3 ret 0
_main ENDP
_TEXT ENDS
---
Для констант выделяется отдельный сегмент. А в релизе наверное подумали, что 4 килобайта (лишний сегмент) только для того, чтобы сунуть туда десяток байт - сильно расточительно и выглядит это так:
PUBLIC _main
PUBLIC ??_C@_0N@LCLI@core?5dumped?4?$AA@ ; `string'
; COMDAT ??_C@_0N@LCLI@core?5dumped?4?$AA@
; File D:\Work\test\test.c
_DATA SEGMENT
??_C@_0N@LCLI@core?5dumped?4?$AA@ DB 'core dumped.', 00H ; `string'
_DATA ENDS
; COMDAT _main
_TEXT SEGMENT
_main PROC NEAR ; COMDAT
; 3 : char *ptr = "core dumped.";
; 4 : *ptr = 'C';
00000 c6 05 00 00 00
00 43 mov BYTE PTR ??_C@_0N@LCLI@core?5dumped?4?$AA@, 67 ; 00000043H
; 5 : }
00007 c3 ret 0
_main ENDP
_TEXT ENDS
---
Не знаю. Если записать побольше констант может им и выделят отдельный сегмент. В любом случае стандарт ничего об этом не говорит (отдает на откуп реализации).
Чтобы не надеяться ни на кого в Visual C можно использовать перед объявлением этой константы
#pragma const_seg(push, ".text")
и
#pragma const_seg(pop)
после
А можно и вообще слить секцию констант с секцией данных или кода (в опциях/ключах линкера или #pragma comment(linker, ...))
Это все касается vc, в остальных компиляторах нечто подобное тоже должно быть.
> > Это ж какой компайлер не понимает стандарта 98-го > года?
> BCC V3.1 от 1992 года и SC V7.2 от 1995 года. > Первый можно кастрировать до необычайно маленьких размеров > так чтоб такать с собой буквально на дискетке. Второй > правильно работает с памятью.
Флешки 128 метровые стоят меньше 20 баксов. Или дискеты это принципиально?
> Попробую.
Не забудь поколдовать над секцией констант, если эта константа глобальная или статическая (в функции/классе), если же это просто
struct A {
int a;
};
void f(const A *a) {
((A *)a)->a = 100;
}
int
main() {
A *a = new A;
A b;
f(a);
f(&b);
return 0;
}
---
То бишь переменная выделена в обычной памяти, но const запрещает ее изменять, то преобразование типов - то что нужно.
|