![](/img/trans.png)
[英]memcpy(), segmentation fault when changing the value of a predefined variable
[英]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 -s
和sizeof()
之間的值。 另外,如果您安裝了 valgrind,請嘗試一下。 valgrind 的 output 可能包含如下內容
你甚至可以調用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.