簡體   English   中英

memcpy 本地 static 變量時出現分段錯誤

[英]Segmentation fault when memcpy local static variable

我遇到了分段錯誤,但我不清楚原因。 我遺漏了一堆東西(希望沒什么重要的)。 有趣的是,它在 valgrind 中進行了全面的泄漏檢查,運行良好,錯誤為 0。 這是所有信息(我正在使用我在網上找到的代碼開發隨機數生成器):

文件1.h

#ifdef __cplusplus
extern "C" {
#endif

#define STATE_N (19937 / 128 + 1)

union W128_T {
   uint32_t u[4];
   uint64_t u64[2];
};

typedef union W128_T w128_t;

struct STATE_T {
    w128_t state[STATE_N];
    int index;
};

typedef struct STATE_T state_t;

#ifdef __cplusplus
}
#endif

使用以下命令將其編譯成 static 庫:

gcc -c -O3 -finline-functions -fomit-frame-pointer -DNDEBUG -fno-strict-aliasing --param max-inline-insns-single=1800 -fPIC -Wmissing-prototypes -Wall -std=c99 src/file1.c -o obj/file1.o
ar rc lib/librand.a obj/file1.o

文件2.h

#include "../rand/include/file1.h"

#ifdef __cplusplus
extern "C" {
#endif

state_t * rstate(void);

#ifdef __cplusplus
};
#endif

文件2.cpp

#include "file2.h"

static state_t rngState;

state_t * rstate(void) {
   return &rngState;
}

文件 2 使用以下命令編譯成 static 庫(省略了一些內容)(來自 cmake,運行 make VERBOSE=1:

/usr/bin/c++ -I/home/random/File1include -I/home/file2include -o CMakeFiles/file2Lib.dir/src/file2.o -c /home/src/file2.cpp

然后我在這個小測試程序 test.cpp 中測試它:

#include "file2.h"
#include <cstring>

int main(void) 
{
   state_t * state = rstate();
   state_t save;

   memcpy(&save, state, sizeof(save)); //segmentation fault
}

我使用以下命令構建(省略內容):

g++ -I/home/random/File1include -I/home/file2include -L/home/file2Lib.dir -Wall -g test.o test.cpp
g++ -I/home/random/File1include -I/home/file2include -L/home/file2Lib.dir -Wall -g test.o -lfile2Lib -o randomTest

如果我將 test.cpp 更改為此它工作正常:

#include "file2.h"
#include <cstring>

int main(void) 
{
   state_t * state = new state_t();
   state = rstate();
   state_t save;

   memcpy(&save, state, sizeof(save));
}

或者,如果我單獨留下 test.cpp 並將 file2.h 更改為:

#include "../rand/include/file1.h"

#ifdef __cplusplus
extern "C" {
#endif

state_t * rstate(void);
state_t rngState;

#ifdef __cplusplus
};
#endif

並將 file2.cpp 更改為:

#include "file2.h"

state_t * rstate(void) {
   return &rngState;
}

該程序也可以正常運行。 最后,如果我將 file2.h 更改為:

#include "../rand/include/file1.h"

#ifdef __cplusplus
extern "C" {
#endif

state_t * rstate(void);
extern state_t rngState;

#ifdef __cplusplus
};
#endif

和 file2.cpp 到這個:

#include "file2.h"

state_t rngState;

state_t * rstate(void) {
   return &rngState;
}

它在測試程序中也有段錯誤。

此外,段錯誤發生在位置state->state[34] 例如,當我嘗試打印出state->state[34].u[0]時。

知道這里發生了什么嗎?

長話短說

想想這個網站叫什么...它是堆棧溢出!


我花了將近一天的時間來解決這個問題。 我的代碼具有與 OP 相同的模式,需要將 static 變量復制到局部變量中。

有問題的變量的類型是使用 C 定義的,但在 C++ 例程中使用。 因此,有可能是C和C++之間的一些不兼容導致了這個問題,這也是我做的第一個檢查。 但是,我放棄了,因為 C 結構應該保證是一個memcpy()可以操作的瑣碎和標准布局。

接下來的動作是一種愚蠢的方式,我檢查了結構的每個成員以找出哪個是惡棍。 借助二分查找的思路,我很快就縮小到了幾個,其中大部分是arrays,數量比較多。 這讓我想起了堆棧溢出。

比較ulimit -ssizeof()之間的值。 另外,如果您安裝了 valgrind,請嘗試一下。 valgrind 的 output 可能包含如下內容

  • 客戶端交換堆棧 SP xxx -> xxx
  • 訪問不在地址 xxx 的映射區域內

你甚至可以調用dmesg並看到類似segfault at xxx ip xxx sp xxx error 6的內容。 https://utcc.utoronto.ca/~cks/space/blog/linux/KernelSegfaultErrorCodes中解釋了error 6

回到 valgrind,實際上它給出了使用--main-stacksize=臨時增加程序上限的提示,可以將其設置為足夠大的值以抑制堆棧問題。 對我來說,然后一切順利。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM