0

爲什麼此代碼在定期運行時產生段錯誤,但未定義的行爲而不是段錯誤,如果我添加命令行參數或註釋掉調用cpy函數?指針段錯誤與未定義的行爲

#include <cstdlib> 
#include <iostream> 
#include <cstring> 
using namespace std; 

int *p; 

void fn() { 
    int n[1]; 
    n[0]=99; 
    p = n; 

} 

void cpy(char *v) { 
    char x[8]; 
    strncpy(x,v,8); 
} 

int main(int argc, char** argv) { 
    fn(); 
    cpy(argv[1]); 
    cout << "p[0]:" << p[0]; 
} 

我知道n是功能fn一個局部變量,但有一個方法可以讓我緩衝區溢出或輸入的東西如argv[1]得到它的打印值不管它是舉行n /是在記憶中?

+2

未定義的行爲?如果添加命令行參數,它將存儲在argv [1]中。如果你註釋掉了cpy()行,那麼你並沒有在任何地方使用argv [1],這就是導致段錯誤的原因。 – Matt

+0

但爲什麼不使用'argv [1]'會導致段錯誤?我的意思是未定義的行爲,打印指向超出範圍變量的'p'的索引。 – Austin

+0

等待,因爲不提供cmdline參數,或不使用變量argv [1]? – Matt

回答

2

如果你沒有通過一個參數,那麼argv[1]==nullptr。然後cpy(argv[1])cpy(nullptr),並且cpy調用strncpy(x,nullptr,8)和段錯誤。

如果你註釋掉了cpy,那麼沒有段錯誤。

如果你傳遞一個參數,那麼cpy將不會segfault。但是,你會遇到一個不同的問題:fn確實是p=n,但是n被聲明在堆棧中,因此返回主cout<<p[0],p指向不再存在的對象n,因此行爲未定義。

+0

謝謝你解釋我95%的困惑。知道一種方法來操縱輸入,以便從'num'所在的位置打印出數據,如果它沒有被覆蓋? – Austin

+0

當你說'num'時,你的意思是在n中聲明的n []嗎?您需要在fn返回之前將其打印出來,或者在fn返回之前將其保存在其他位置。 – Waxrat

+0

對不起''[]'我基本上是在不改變代碼的情況下讓主打印出'99'。 – Austin