2010-07-01 82 views
5

我有一個頭文件中定義一個結構如下:爲什麼在全局或外部聲明結構時會出現段錯誤?

#define LC_ERR_LEN 300 
typedef struct dLC_ERRMSG { 
    short nr; 
    short strategy; 
    char tx[LC_ERR_LEN]; 
} LC_ERRMSG; 

,我在我的代碼中使用這樣:

LC_ERRMSG err; 
char *szError; 
szError = strerror(sStatus); 
snprintf(err.tx,LC_ERR_LEN," %s - %s",szFilename,szError); 
/* do something with our error string */ 

工程。但是,如果我在全局聲明LC_ERRMSG err; - 即在其使用的函數外部,或者甚至是extern LC_ERRMSG err;(這是我的初衷,因爲我希望能夠讀出中央位置的錯誤狀態),代碼段錯誤snprintf調用。

你能給我一些線索爲什麼嗎?

ddd告訴我,當全局聲明時,內存被初始化爲全零,或者至少在聲明extern時被初始化和可讀。值szFilename,szError和LC_ERR_LEN都是正確和有意義的。

+5

這看起來像C,而不是C++? – 2010-07-01 13:59:32

+1

變量名稱看起來像一隻貓正在穿過鍵盤。 – 2010-07-01 14:19:29

+2

這是一隻匈牙利貓,因爲我確定Freakzoid的貓也是。 – maxwellb 2010-07-01 14:24:13

回答

3

你的連接可以簡單地扔掉符號,它認爲不使用(GNU鏈接這樣做) 。在這種情況下,您可以顯式鏈接目標文件和該符號。

使用C++,您無法控制在其他編譯單元中定義的全局對象的初始化順序(請參閱http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12)。

使用「首次使用時的構造」成語,它僅僅意味着將靜態對象包裹在函數中。

+0

非常感謝!這解決了它。 – relet 2010-07-02 08:25:34

2

如果您有:

// structs.hpp 
#define LC_ERR_LEN 300 
typedef struct dLC_ERRMSG { 
    short nr; 
    short strategy; 
    char tx[LC_ERR_LEN]; 
} LC_ERRMSG; 

和:

// main.cpp 
#include "structs.hpp" 
LC_ERRMSG err; 

int main() 
{ 
    // ... 

    char *szError; 
    szError = strerror(sStatus); 
    snprintf(err.tx, LC_ERR_LEN, "%s - %s", szFilename, szError); 
} 

那麼這應該工作。但是,如果您切換的main.cpp下聯:

extern LC_ERRMSG err; 

,那麼你需要確保爲err存儲被編譯成目標文件之一。例如,你可以編譯這個源:

// globals.cpp 
#include "structs.hpp" 

LC_ERRMSG err; 

所得globals.o鏈接到main.o

任何一種方法都不應引起分段錯誤。如果您遇到分段錯誤,那麼編譯globals.cpp時,編譯main.cpp時,問題可能是LC_ERR_LEN有不同的值。或者,也許szFilenameszErrorNULL /壞。 printf系列無法打印NULL或格式標記爲%s的錯誤指針;下面的代碼會導致分段錯誤:

#include <stdio.h> 

int main() 
{ 
    printf("%s\n", NULL); 
} 

編輯:我認爲問題的另一個潛在原因。如果您使用的是C編譯器,則可能會出現符號衝突,因爲err是一個符號,可用作大型項目中幾個不同全局變量的名稱。如果您使用的是C++編譯器,那麼名稱修改過程應確保每個err都有自己的符號。只要確保你正在編譯爲C++。

+0

感謝您的回答和麥克斯韋爾伯的答覆。在我試圖通過在其他地方聲明「err」來縮小問題之前,發佈的workforme maxwellb與我最初的代碼相似。我也正在用g ++編譯爲C++。到目前爲止沒有運氣。 困擾我的是我不知道err.tx如何被破壞,即使在此期間還有其他代碼正在使用它。它沒有被動態分配,所以我可以意外釋放它。 – relet 2010-07-01 15:12:42

+0

使用你的調試器,你會驗證szFilename和szError在snprintf行不是''NULL','szFilename'是正確的空終止?另外,什麼是地址'err.tx'? – 2010-07-01 16:20:03

2

丹尼爾答案+1。這是一個適合我的作品。適合你嗎? Upvote丹尼爾的答案。


// structs.hpp 
#define LC_ERR_LEN 300 
typedef struct dLC_ERRMSG { 
    short nr; 
    short strategy; 
    char tx[LC_ERR_LEN]; 
} LC_ERRMSG; 

// error.cpp 
#include "structs.hpp" 

LC_ERRMSG err; 

// main.cpp 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include "structs.hpp" 
extern LC_ERRMSG err; 

int main() 
{ 
    // ... 
    char *szFilename = "EXAMPLE.LOG"; 
    int sStatus = 0; 
    char *szError; 
    szError = strerror(sStatus); 
    snprintf(err.tx, LC_ERR_LEN, "%s - %s", szFilename, szError); 

    printf("err.tx: %s", err.tx); 
} 

// Output: 
err.tx: EXAMPLE.LOG - No error 
相關問題