2013-05-10 77 views
1

我試圖得到段錯誤,但我無法得到它,我想知道爲什麼。C++試圖失敗構造函數

#include <iostream> 
using namespace std; 


class A{ 

public: 
    char *field_; 

    A(char *field):field_(field) { 
    // I believe(suppose) that it's equal to 
    // field_ = field; 
    // so actual initial string wasn't copied, only a pointer to it 
    } 
void show() { 
    cout<<field_<<"\n"; 
} 
}; 

int main(){ 

    A *obj; 

{ 
    char *line="I should be freed"; 
    obj = new (nothrow) A(line); 
} 

    // After exiting from the previous scope, 
    // char *line variable should be freed. 
    // Constructor of class A didn't make byte for byte 
    //copying, so we cannot have 
    // access to it for sure 

for(int i=0;i<4;i++) // trying to clear stack and erase char *line variable 
char something[10000]; 

obj->show(); // and it works correctly!!!! why? 


delete obj; 
return 0; 
} 

好的,據我所知,它只是因爲該字符串沒有從內存中釋放正常工作。 也就是說我們只是幸運。 而這裏我們有未定義的行爲。我對嗎?

預先感謝您!

+0

爲什麼要向堆棧中添加*東西來清除堆棧中已經存在的東西? (不是字符串本身在堆棧中) – Andrei 2013-05-10 21:30:04

+0

如果字符串已經被分配到堆棧中,並且我們超出了範圍,所使用的內存被標記爲不必要,所以如果我們要求新的內存有一些概率,必要的內存將被使用,並且舊的字符串將被擦除(當然,不能保證完全取出內存)。例如。它並不適用於我的情況,即使在我將其定義爲char line [80] =「我應該被釋放」的情況下,在堆棧中,因爲該內存不僅僅是被佔用的。但有時它可以被覆蓋,有時不可以。糾正我,如果我錯了 – Tebe 2013-05-10 21:33:05

+0

是的,錯過了標記範圍的榮譽... – Andrei 2013-05-10 21:41:40

回答

4

由於程序沒有無效的內存引用,所以不會出現分段錯誤。我猜你認爲""I should be freed"是在堆棧上創建的,然後以某種方式被銷燬或釋放,並且這是一個錯誤的假設,因爲它是一個常量字符串文本,它被放置到程序數據段中並且對於您的生活「活着」程序。

即使它是在離開示波器時動態分配和自動釋放的,您仍然無法期望您的程序在該情況下會收到SIGSEGV。因爲未定義的行爲並不總是導致分段錯誤。

另外,儘量不要寫char *data = "blah-blah";。假定字符串文字始終保持不變,並試圖修改它們是未定義的行爲。儘管人們仍然對這個sometimes進行破解。

+0

好的,謝謝,如果我將它定義爲char line [80] =「我應該被釋放」,它應該分配在堆棧,是嗎? – Tebe 2013-05-10 21:22:42

+1

@gekannt是的,'line'駐留在堆棧上。字符串文字被複制到數組中。 – Mahesh 2013-05-10 21:24:41

+1

@gekannt:是的,這會觸發未定義的行爲,但不一定是分段錯誤,因爲堆棧內存在技術上仍然存在。所以偶然它可能仍然有效,或者它可能會打印垃圾或崩潰。 – 2013-05-10 21:24:52

2
char *line = "I should be freed"; 

您仍然可以看到內容,因爲字符串文字具有靜態存儲持續時間。這裏的字符串文字I should be freed駐留在只讀位置,並在程序執行完成後釋放。

該程序沒有未定義的行爲。