fgetc在第二次运行后导致段错误

时间:2017-10-26 11:54:04

标签: python c segmentation-fault fgetc

我有一个尝试读取特定密钥文件的应用程序,这可能会在程序的生命周期中多次发生。以下是读取文件的功能:

__status 
_read_key_file(const char * file, char ** buffer)
{
    FILE * pFile = NULL;
    long fsize = 0;

    pFile = fopen(file, "rb");
    if (pFile == NULL) {
        _set_error("Could not open file: ", 1);
        return _ERROR;
    }

    // Get the filesize
    while(fgetc(pFile) != EOF) {
        ++fsize;
    }

    *buffer = (char *) malloc(sizeof(char) * (fsize + 1));

    // Read the file and write it to the buffer
    rewind(pFile);

    size_t result = fread(*buffer, sizeof(char), fsize, pFile);

    if (result != fsize) {
        _set_error("Reading error", 0);
        fclose(pFile);
        return _ERROR;
    }

    fclose(pFile);
    pFile = NULL;

    return _OK;
}

现在的问题是,对于单个打开/读取/关闭它可以正常工作,除非我第二次运行该函数 - 它总是会在此行进行段错误:while(fgetc(pFile) != EOF)

跟踪gdb,它表明segfault在fgetc函数本身内发生得更深。 我有点失落,但显然我做错了,因为如果我试着用fseek / ftell告诉大小,我总是得到0。

某些背景信息:

  • 语言:C
  • 系统:Linux(Ubuntu 16 64bit)
  • 请忽略功能 和带有下划线的名称,因为它们被定义在其他地方 代码。
  • 程序旨在作为动态库运行,以通过ctypes
  • 加载Python

修改 是的,似乎不只是满足于眼睛。让 - 弗朗索瓦·法布尔(Jean-FrançoisFabre)产生了一个我测试过的想法并且它有效,但我仍然对此感到困惑。

一些额外的背景:

假设C中有一个看起来像这样的函数:

_status 
init(_conn_params cp) {

    _status status = _NONE;

    if (!cp.pkey_data) {
        _set_error("No data, open the file", 0);

        if(!cp.pkey_file) {
            _set_error("No public key set", 0);
            return _ERROR;
        }

        status = _read_key_file(cp.pkey_file, &cp.pkey_data);
        if (status != _OK) return status;
    }

    /* SOME ADDITIONAL WORK AND CHECKING DONE HERE */

    return status;
}

现在在Python中(使用3.5进行测试),我们生成那些conn_params,然后调用init函数:

from ctypes import *

libCtest = CDLL('./lib/lib.so')

class _conn_params(Structure):
    _fields_ = [
        # Some params

        ('pkey_file', c_char_p),
        ('pkey_data', c_char_p),

        # Some additonal params
    ]

#################### PART START #################
cp = _conn_params()
cp.pkey_file = "public_key.pem".encode('utf-8')

status = libCtest.init(cp)
status = libCtest.init(cp) # Will cause a segfault
##################### PART END ###################

# However if we do

#################### PART START #################
cp = _conn_params()
cp.pkey_file = "public_key.pem".encode('utf-8')
status = libCtest.init(cp)

# And then

cp = _conn_params()
cp.pkey_file = "public_key.pem".encode('utf-8')
status = libCtest.init(cp)

##################### PART END ###################

第二个PART START / PART END不会在这种情况下导致段错误。

有人知道原因吗?

0 个答案:

没有答案