Tag: undefined behavior

realloc()悬空指针和未定义的行为

当你释放内存时,指向内存的指针会发生什么? 他们立即变得无效吗? 如果他们以后再次有效会怎么样? 当然,指针变为无效然后再次变为“有效”的通常情况是将某些其他对象分配到之前使用的内存,如果使用指针访问内存,那显然是未定义的行为。 悬空指针内存覆盖了第1课,差不多。 但是,如果内存再次对同一分配有效,该怎么办? 只有一种标准方式可以实现: realloc() 。 如果你有一个指向malloc() ‘内存块中偏移量> 1某个位置的指针,那么使用realloc()将块缩小到小于你的偏移量,显然你的指针变得无效。 如果你再使用realloc()再次将块增长回至至少覆盖悬空指针指向的对象类型,并且在任何情况下都没有realloc()移动内存块,悬空指针是否再次有效? 这是一个极端的案例,我真的不知道如何解释C或C ++标准来解决它。 以下是显示它的程序。 #include #include #include int main(void) { static const char s_message[] = “hello there”; static const char s_kitty[] = “kitty”; char *string = malloc(sizeof(s_message)); if (!string) { fprintf(stderr, “malloc failed\n”); return 1; } memcpy(string, s_message, sizeof(s_message)); printf(“%p %s\n”, string, string); […]

为什么我们可以在C语言之外写入?

我最近读完了有关虚拟内存的内容,我对于malloc如何在虚拟地址空间和物理内存中工作有疑问。 例如(从另一个SOpost复制的代码) void main(){ int *p; p=malloc(sizeof(int)); p[500]=999999; printf(“p[0]=%d\n”,p[500]); //works just fine. } 为什么允许这种情况发生? 或者为什么p [500]的地址甚至可写? 这是我的猜测。 当调用malloc时,操作系统可能会决定为进程提供整个页面。 我将假设每个页面的空间值为4KB。 整个事情是否被标记为可写? 这就是为什么你可以到500 * sizeof(int)进入页面(假设32位系统,其中int的大小为4字节)。 当我尝试以更大的值编辑时,我看到了… p[500000]=999999; // EXC_BAD_ACCESS according to XCode 段故障。 如果是这样,那么这是否意味着有些页面专用于您的代码/指令/文本段并标记为不可写入与您的堆栈/变量所在的页面完全分离(事情发生变化)并标记为可写? 当然,该过程认为它们位于32位系统上4gb地址空间中的每个订单旁边。

C – 函数返回指向局部变量的指针

请考虑以下代码。 #include int *abc(); // this function returns a pointer of type int int main() { int *ptr; ptr = abc(); printf(“%d”, *ptr); return 0; } int *abc() { int i = 45500, *p; p = &i; return p; } 输出: 45500 我知道根据链接这种行为是未定义的。 但是为什么每次运行程序时我都能获得正确的值。

scanf对于short int的奇怪行为

代码如下: #include main() { int m=123; int n = 1234; short int a; a=~0; if((a>>5)!=a){ printf(“Logical Shift\n”); m=0; } else{ printf(“Arithmetic Shift\n”); m=1; } scanf(“%d”,&a); printf(“%d\n”, m); } 在行scanf(“%d”,&a); m的值变为0 。 我知道它可能是由scanf引起的:a的类型很短,输入的类型是int。 但这怎么会影响m的价值呢? 非常感谢 !

为什么在C中允许未定义的行为

我最近一直在努力学习C。 来自Java,它让我感到惊讶,你可以执行声明为“未定义”的某些操作。 这对我来说似乎非常不安全。 我理解程序员不负责执行未定义的操作,但为什么它甚至可以从一开始就被允许? 为什么编译器没有捕获,例如,数组索引超出界限,甚至悬挂指针? 你最终只能访问你永远不应该访问的内存块,没有明显的理由。 作为比较,Java 更加确定你不会做任何愚蠢的事情 ,像热饼一样抛出exception。 当然必须有一个理由允许这样做吗? 它是什么? 答案:据我了解,主要原因是表现。 此外,Java确实有未定义的行为,尽管没有这样标记。 编辑:限制问题到C

C中的unsigned int表现为负数

我不明白为什么unsigned int的输出对于以下代码是负的。 就像一个签名的int。 uint32_t yyy=1<<31; printf("%d\n",yyy); 输出是: -2147483648 这是-2^31 。

为什么程序访问指针的非法指针不会崩溃?

访问指针非法指针的程序不会因SIGSEGV而崩溃。 这不是一件好事,但我想知道这可能是什么以及这个过程如何在生产中存活了很多天。 这对我来说很困惑。 我已经将这个程序用于Windows,Linux,OpenVMS和Mac OS,他们从未抱怨过。 #include #include void printx(void *rec) { // I know this should have been a ** char str[1000]; memcpy(str, rec, 1000); printf(“%*.s\n”, 1000, str); printf(“Whoa..!! I have not crashed yet :-P”); } int main(int argc, char **argv) { void *x = 0; // you could also say void *x = (void […]

为什么参数与printf未定义的行为中的转换说明符不匹配?

在C(n1570 7.21.6.1/10)和C ++(通过包含C标准库)中,为printf提供参数是未定义的行为,其类型与其转换规范不匹配。 一个简单的例子: printf(“%d”, 1.9) 格式字符串指定int,而参数是浮点类型。 这个问题的灵感来自一个用户遇到遗留代码的问题,这些代码存在大量的转换不匹配,这显然没有任何损害,参见 理论上和实践中未定义的行为 。 声称格式不匹配UB起初看起来很激烈。 很明显, 输出可能是错误的,具体取决于精确的不匹配,参数类型,字节序,可能的堆栈布局和其他问题。 正如一位评论员指出的那样,这也延伸到后来的(甚至是之前的?)论点。 但这远不是一般的UB。 就个人而言,除了预期的错误输出外,我从未遇到任何其他问题 冒险猜测,我会排除对齐问题。 我能想象的是提供一个格式字符串,使printf期望大数据和小的实际参数可能让printf读取超出栈,但我缺乏对var args机制和特定printf实现细节的深入了解来validation。 我快速浏览了printf源代码 ,但它们对于休闲读者来说非常不透明。 因此我的问题是:在printf中错误匹配转换说明符和参数的具体危险是什么使它成为UB?

什么是“*((char *) – 1)=’x’;”代码是什么意思?

我在阅读redis源代码时遇到问题,有人能告诉我_redisAssert函数中最后一个语句的_redisAssert是什么 : *((char*)-1) = ‘x’;

在C中反转一个字符串

我知道这已被问过几千次,但我在代码中找不到错误。 有人可以指出我做错了什么吗? #include #include void reverseString(char *myString){ char temp; int len = strlen(myString); char *left = myString; // char *right = &myString[len-1]; char *right = myString + strlen(myString) – 1; while(left < right){ temp = *left; *left = *right; // this line seems to be causing a segfault *right = temp; left++; right–; } } […]