6

我在标题中定义了一个结构,如下所示:

#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 都是正确且有意义的。

4

3 回答 3

3

您的链接器可以简单地丢弃它认为未使用的符号(GNU 链接器这样做)。在这种情况下,您可以显式地将目标文件与该符号链接。

使用 C++,您无法控制在其他编译单元中定义的全局对象的初始化顺序,而无需任何额外的努力(请参阅http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12)。

使用“construct on first use”的习惯用法,这只是意味着将静态对象包装在一个函数中。

于 2010-07-01T18:04:34.710 回答
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.omain.o.

任何一种方法都不应导致分段错误。如果您遇到分段错误,那么问题可能是编译时LC_ERR_LEN的值与编译时的值不同。或者,也许或者是/坏的。该族无法打印或带有格式标志的错误指针;以下代码导致分段错误:globals.cppmain.cppszFilenameszErrorNULLprintfNULL%s

#include <stdio.h>

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

编辑:我想到了问题的另一个潜在原因。如果您使用 C 编译器,可能会出现符号冲突,因为err符号可以用作大型项目中多个不同全局变量的名称。如果您使用的是 C++ 编译器,则名称修改过程应确保每个err都有自己的符号。只需确保您正在编译为 C++。

于 2010-07-01T13:58:32.480 回答
2

+1 丹尼尔的回答。这是我的作品。适合你吗?支持丹尼尔的回答。


// 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
于 2010-07-01T14:21:54.033 回答