堆栈上的字符数组导致段错误
char array on stack causes seg fault
这可能是预料之中的,但我只是好奇 how/why 会发生这种情况。
当我尝试使用在本地 char * foo = "\xFF\xFF..."
声明的 char *
作为整数时,它会出现段错误。但是,如果我使用 malloc,当我尝试访问它时,它运行得非常好。为什么会这样?
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
unsigned char *buf = malloc(16);
memcpy(buf, "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 16);
//unsigned char *buf = "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; // seg faults if you sue this instead
uint64_t *k = (uint64_t *) buf;
uint64_t *k2 = (uint64_t *) (buf + 8);
uint64_t i = 1000000000;
printf("-k =%" PRIu64 "\n", *k);
printf("-k2=%" PRIu64 "\n", *k2);
printf("Iter * %" PRIu64 "\n", i);
for (uint64_t c = 0; c < i; ++c)
{
*k += 1;
*k2 -= 1;
}
printf("-k =%" PRIu64 "\n", *k);
printf("-k2=%" PRIu64 "\n", *k2);
return 0;
}
输出:
easytiger $ gcc -std=c99 tar.c -Wall -O2 ; time ./a.out
-k =0
-k2=18446744073709551615
Iter * 1000000000
-k =1000000000
-k2=18446744072709551615
不能保证字符串文字将存储在可写内存页中。这意味着 for 循环中的 *k += 1
操作可能会尝试写入只读内存。另一方面,由 malloc
分配的内存将始终是可写的。
对于这种形式的定义:
unsigned char *buf = "some string";
buf
指向存储在内存只读部分中的静态字符串。当您尝试写入它时,会出现段错误。
通过使用malloc
,buf
指向的内存是可写的。
字符串文字是不可变的。您不得修改存储在那里的数据。曾经.
即使在现在的 C 语言中,我们也通过将 const
放入指针类型来使这一点变得清晰和可诊断。
C++ 实际上需要它。
这可能是预料之中的,但我只是好奇 how/why 会发生这种情况。
当我尝试使用在本地 char * foo = "\xFF\xFF..."
声明的 char *
作为整数时,它会出现段错误。但是,如果我使用 malloc,当我尝试访问它时,它运行得非常好。为什么会这样?
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
unsigned char *buf = malloc(16);
memcpy(buf, "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 16);
//unsigned char *buf = "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; // seg faults if you sue this instead
uint64_t *k = (uint64_t *) buf;
uint64_t *k2 = (uint64_t *) (buf + 8);
uint64_t i = 1000000000;
printf("-k =%" PRIu64 "\n", *k);
printf("-k2=%" PRIu64 "\n", *k2);
printf("Iter * %" PRIu64 "\n", i);
for (uint64_t c = 0; c < i; ++c)
{
*k += 1;
*k2 -= 1;
}
printf("-k =%" PRIu64 "\n", *k);
printf("-k2=%" PRIu64 "\n", *k2);
return 0;
}
输出:
easytiger $ gcc -std=c99 tar.c -Wall -O2 ; time ./a.out
-k =0
-k2=18446744073709551615
Iter * 1000000000
-k =1000000000
-k2=18446744072709551615
不能保证字符串文字将存储在可写内存页中。这意味着 for 循环中的 *k += 1
操作可能会尝试写入只读内存。另一方面,由 malloc
分配的内存将始终是可写的。
对于这种形式的定义:
unsigned char *buf = "some string";
buf
指向存储在内存只读部分中的静态字符串。当您尝试写入它时,会出现段错误。
通过使用malloc
,buf
指向的内存是可写的。
字符串文字是不可变的。您不得修改存储在那里的数据。曾经.
即使在现在的 C 语言中,我们也通过将 const
放入指针类型来使这一点变得清晰和可诊断。
C++ 实际上需要它。