代码之家  ›  专栏  ›  技术社区  ›  relet

为什么在全局或外部声明结构时会出现segfaults?

  •  5
  • relet  · 技术社区  · 14 年前

    我在头文件中定义了一个结构,如下所示:

    #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;

    你能告诉我为什么吗?

    ddd告诉我,内存在全局声明时被初始化为全零,或者在外部声明时至少被初始化并可读。值szFilename、szError和LC\u ERR\u LEN都是正确且有意义的。

    3 回复  |  直到 14 年前
        1
  •  3
  •   Sergey    14 年前

    您的链接器可以简单地丢弃它认为没有使用的符号(GNU链接器就是这样做的)。在这种情况下,可以显式地将对象文件与该符号链接起来。

    在没有任何额外的努力的情况下,C++无法控制在其他编译单元中定义的全局对象的初始化顺序。 http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 ).

    使用“construct on first Use”习惯用法,简单地说就是将静态对象包装到函数中。

        2
  •  2
  •   Daniel Trebbien    14 年前

    如果您有:

    // 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

    这两种方法都不应导致分割错误。如果您遇到分割错误,那么问题可能是 LC_ERR_LEN globals.cpp 正在编译 主.cpp 正在编译。或者,也许 szFilename szError NULL printf 家庭无法打印 无效的 %s ; 以下代码导致分段错误:

    #include <stdio.h>
    
    int main()
    {
        printf("%s\n", NULL);
    }
    

    有自己的标志。只需确保你正在编译为C++。

        3
  •  2
  •   maxwellb    14 年前


    // 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