[英]Trying to understand what is wrong with the following code in C
我有一個任務來查找為什么此代碼錯誤。
#include <stdlib.h>
#include <stdio.h>
#define fail(a) ((test == 0 || test == a) ? fail##a() : 0)
#define N (10)
int a[N] = { 1 };
int* b = &a[0];
void fail1()
{
printf("a[0] = %d\n", a[0]);
printf("b[0] = %d\n", b[0]);
printf("*b = %d\n", *b);
*b = 2;
a[N] = 3;
printf("*b = %d\n", *b);
}
...
int main(int argc, char **argv)
{
int test = 0;
if (argc > 1) {
sscanf(argv[1], "%d", &test);
printf("doing test %d\n", test);
} else
puts("doing all tests");
fail(1);
fail(2);
fail(3);
fail(4);
fail(5);
fail(6);
puts("lab6 reached the end");
exit(0);
}
通過使用valgrind,它告訴我printf("*b = %d\\n", *b);
失敗printf("*b = %d\\n", *b);
。 我注意到,通過評論a[N] = 3;
valvgrind沒有給出任何錯誤。 但是我不明白為什么。 我知道這與內存有關,我知道a[N]
要求數組外的元素。
C數組具有從0開始的索引。 對於定義為a[N]
的數組,最大有效元素將為a[N-1]
。
a[N]
指向超出范圍的內存。 嘗試訪問超出范圍的內存會調用未定義的行為 。
現在,雖然您可能知道上述事實,但是您可能忽略了UB的作用。 一旦打到UB,便無法保證。 簡單的解決方案,不要編寫可以調用UB的代碼。
數組索引從0開始,因此最后一個索引a
是N-1
不N
。 通過寫入a[N]
您正在訪問的內存不是數組的一部分,從而導致未定義的行為 。
C中沒有數組邊界檢查。a [N]位於數組末尾,即a [0] .. a [N-1]
如果您在數組范圍之外進行讀取或寫入,則會得到隨機結果(如今人們將UB稱為UB“未定義的行為”)。 這可能是
讀x = a[outside];
寫a[outside] = x;
例如,假設a []是char數組。
a[0] | a[1] | ... | a[N-1] | s[0] | s[1] | s[2] | s[3] | s[4] | s[5]
1 | 0 | | 7 | 'H' | 'e' | 'l' | 'l' | '0' | 0
寫入a [N]不會更改數組,而是會覆蓋另一個變量(在這種情況下,是字符串的一部分)。 您破壞了程序的內存,導致混亂。
a[N] = 255; /*bug*/
a[0] | a[1] | ... | a[N-1] | s[0] | s[1] | s[2] | s[3] | s[4] | s[5]
1 | 0 | | 7 | 255 | 'e' | 'l' | 'l' | '0' | 0
在此示例中,讀取和寫入a [N]似乎可以工作,但是它破壞了另一個字符串變量(該字符串變量以前表示“ Hello”,但現在沒有)。 這可能會在以后導致錯誤,或者也許多年來沒人會注意到!
使用C進行編程時,您需要格外小心和紀律。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.