2016-10-11 78 views
-1

以下代碼有什麼問題? memset應該使用指針指向要填充的內存塊。但是這個代碼顯示在控制檯說分割故障問題(核心轉儲)自2011年memset無法使用指向字符的指針

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

int main(int argc, char** argv) 
{ 
    char* name = "SAMPLE TEXT"; 
    memset(name , '*', 6); 
    cout << name << endl; 
    return 0; 
} 

screenshot of the above program catching a segmentation fault

+0

請勿在此發佈文字圖片。發佈文字。 – EJP

回答

3

這不是有效的C++代碼,和之前曾經有過UB。它是C中的UB。

C++≥11:不能將字符串文字指定給非constchar指針。

C++≥98和C:您不能覆蓋字符串文字。

更改您的代碼

char name[] = "SAMPLE TEXT"; 

,你就會有一個本地陣列可以被覆蓋。

0

該代碼嘗試修改字符串文字("SAMPLE TEXT")的內容。這是不允許的。

7

你已經絆倒了一個非常古老的向後兼容疣的C++,從C繼承和約會的日期沒有這樣的事情const。字符串文字的類型爲const char [n],但是,除非您告訴編譯器,您不需要與1990年代以前的代碼兼容,否則它將默默地允許您設置char *變量指向它們。但它不會允許你通過這樣的指針寫入。實際的內存(只要可能)標記爲只讀;您觀察到的「分段錯誤」錯誤是操作系統報告嘗試寫入只讀內存的方式。

根據語言規範,通過非const指針寫入const指針 - 但是,您設法設置了這個指針 - 有「未定義的行爲」,這是一種奇怪的方式:「程序不正確,但編譯器不必發出診斷信息,如果你得到一個編譯好的可執行文件,它可能會做什麼。「 「分段錯誤」幾乎總是意味着您的程序在某處存在未定義的行爲。

如果我有適當的設置編譯你的程序,我得到一個錯誤:直到你獲得足夠的技能,知道什麼時候不同的設置是比較合適的

$ g++ -std=gnu++11 -Wall -Werror test.cc 
test.cc: In function ‘int main(int, char**)’: 
test.cc:7:19: error: ISO C++ forbids converting a string constant to ‘char*’ 
[-Werror=write-strings] 
     char* name = "SAMPLE TEXT"; 
        ^~~~~~~~~~~~~ 

,編譯所有你的C++程序與-std=gnu++11 -Wall -Werror,或者不管你的編譯器是什麼。 (你似乎是使用Unix的味道操作系統,所以這些設置應該工作。您可能還需要-g和/或-O。)

可以使你的程序,通過改變它的工作看

#include <iostream> 
#include <cstring> 

int 
main() 
{ 
    char name[] = "SAMPLE TEXT"; 
    std::memset(name, '*', 6); 
    std::cout << name << '\n'; 
    return 0; 
} 

=>

$ g++ -std=c++11 -Wall -Werror test.cc 
$ ./a.out 
****** TEXT 

固定所述錯誤是從char *namechar name[]的變化;我改變了其他一些東西,但只是爲了展現更好的風格。這樣做會迫使編譯器在輸入main時將字符串文字複製到可寫內存。 爲什麼這樣做會花費很長時間來解釋;請教一個好的C++教科書。