C 通过静态库链接时功能不正常,但在程序中复制时功能正常
我有一个静态库(.a),其中包含一些在另一个程序中使用的有用函数。 链接进行得很顺利,找到了库中的函数,但是当程序执行时,它就不能正常工作。另一方面,如果我直接在程序代码中复制/粘贴我需要的lib函数,它工作得很好。此外,它在win32上运行良好,但现在我使用的是Win64 Edit:我知道代码很糟糕(不是我的),但直接复制到prog中时,它仍能正常工作,这意味着开发人员不会对其进行任何更改。我需要理解的是,当我链接函数所在的库时,为什么它不能很好地工作,而它在Linux64和Win32上工作得很好。您可能会在这段代码中发现很多问题,但这只是一个示例;因为它没有解释为什么它在prog中工作,但没有被lib链接,所以它对我来说毫无用处,因为开发人员根本不关心它。 下面是lib中有问题的函数之一(我使用了最简单的函数,它对lib的依赖性不大,但我怀疑其他函数没有按预期工作): 这个函数在MyLib.a中。我使用Mingw64在Win64上编译它(就像我在Win32上使用Mingw一样),编译工作正常。 然后,在编译MyProg时,我链接这个库。汇编进展顺利。 当我启动MyProg时,它会在某个时候使用此功能,并在C 通过静态库链接时功能不正常,但在程序中复制时功能正常,c,static-libraries,win64,C,Static Libraries,Win64,我有一个静态库(.a),其中包含一些在另一个程序中使用的有用函数。 链接进行得很顺利,找到了库中的函数,但是当程序执行时,它就不能正常工作。另一方面,如果我直接在程序代码中复制/粘贴我需要的lib函数,它工作得很好。此外,它在win32上运行良好,但现在我使用的是Win64 Edit:我知道代码很糟糕(不是我的),但直接复制到prog中时,它仍能正常工作,这意味着开发人员不会对其进行任何更改。我需要理解的是,当我链接函数所在的库时,为什么它不能很好地工作,而它在Linux64和Win32上工作得
strncpy
上停止(之前使用了memcpy
,但效果并不好)。它不会抛出任何错误消息,什么也没有:我等了一会儿,程序停止了,就好像它做得很好一样,只是没有。如果我尝试在这个strncpy
之后进行打印,它永远不会转到它,但是程序结束“正常”(我看不到崩溃)
奇怪的是,如果我把这个函数复制/粘贴到MyProg的代码中,比如说我称它为readFileBis
,那么readFileBis
工作得很好
然而,我不会在每个需要它的程序中复制/粘贴库的每个函数。那将是一种浪费
编辑:试图为其制作一个可复制的示例,但仍在进行。假设这是MyProg的唯一文件:
MyProg.c
#define FILENAME "MyDir/ParamFile.txt"
void readParamFileBis (char* filename, UI8* *Params, I64 *ParamsLen){
//the exact same thing as in readFile, don't wanna make the question too long.
}
int main(int argc, char *argv[]){
UI8 *Params = NULL;
I64 ParamsLen = 0;
//this is working:
readParamFileBis (FILENAME, &Params, &ParamsLen);
//this is not working :
readParamFile (FILENAME, &Params, &ParamsLen);
exit(0);
}
ParamFile.txt看起来很像(数字更长):
我想知道这里可能出了什么问题。知道它在Win32上运行良好,我想它与64位的东西有关,但我不知道是什么。因为我在win64上重新编译了lib和prog,所以应该没问题。我不知道发生了什么事
哦,还有一件奇怪的事情可能与此有关,也可能与此无关:在编译时,我可能会使用标志-D${ARCHI}。在Win32上,ARCHI是mnigw386
;在win64上,它是mingwx64
。当我在Win64上使用此标志进行编译时,我得到了一些关于我的打印格式的警告(例如,我正在使用%ld打印一些在win32上没有的I64,但它不喜欢)
编辑/解决方案:所以问题确实出在I64上。我设法通过
int64\t
更改了它,它正在工作。此外,我成功地重新发布了Makefiles(从250行和16个目标到90行和5个目标…),然后发现架构确实已经定义了…但没有包含在任何编译标志中。所以我猜prog看不到I64
被定义为long
(因为它在中,如果mingwx64
),并且认为它是long
,这是这里的大问题 Windows是LLP64而不是LP64;只有在为x64编译时,I64才只有32位,高位作为垃圾传递
请务必包含,并使用诸如int64_t和uint64_t之类的类型来避免此类错误
不纠正错误的定义是行不通的。如果必须,请使用应用修补程序的生成过程,但要使用工作类型定义。发布的代码片段中存在多个问题:
不正确。您应该将反斜杠转义为#定义文件名“MyDir\ParamFile.txt”
,或者使用适用于所有Windows版本的普通正斜杠:#定义文件名“MyDir\\ParamFile.txt”
#定义文件名“MyDir/ParamFile.txt”
- 类型
的任意定义是有风险的。您应该包括I64
并使用typedef uint64代码>
- 函数原型
与预期的API不一致:void readFile(char*filename,UI8*Params,I64*ParamsLen)
读取文件内容,并将指向已分配缓冲区长度readFile
的指针存储到*ParamsLen
中。原型应为:*Params
int readFile(const char *filename, UI8 **Params, I64 *ParamsLen);
应返回错误代码,以防文件无法打开或读取readFile
退出(-1)后缺少
代码>在函数}
中readFile
- 临时缓冲区应该分配一个额外的字节,以防文件包含一行,而不是以换行符结尾
不一定在数组末尾存储fgets()
,尤其是当文件不包含一个时。无条件剥离最后一个字符是不正确的'\n'
- 为什么不使用
malloc()
- 如果希望将文件内容用作C字符串,则应为空终止符分配额外的字节,并将其存储在数组的末尾
# Introduction text
000500000000064F1B58372A27
int readFile(const char *filename, UI8 **Params, I64 *ParamsLen);
void readParamFile (char* filename, UI8 *Params, I64 *ParamsLen){
*Params=NULL
*Params= (UI8*)PtrAlloc(sizeof(UI8)*strlen(buf))
void readParamFile (char* filename, UI8 **Params, I64 *ParamsLen)
#include <stdio.h>
#include <string.h>
#include <stdint.h>
int readParamFileBis( const char *filename, unsigned char **params, uint64_t *paramsLen )
{
*params = NULL;
FILE *fp = fopen( filename, "r" );
if ( fp == NULL )
{
return( -1 );
}
// assume we have POSIX getline()
// (Windows implementations abound...)
unsigned char *line = NULL;
size_t lineLen = 0UL;
// loop until a line that doesn't start with # is found
for ( ;; )
{
ssize_t bytesRead = getline( &line, &lineLen, fp );
// EOF - no more to read
if ( bytesRead == -1 )
{
break;
}
// line starts with # - skip it
if ( line[ 0 ] == '#' )
{
continue;
}
// we found the first line that
// doesn't start with #, so pass
// it back to the caller
// strip any trailing newline
line[ strcspn( "\n" ) ] = '\0';
// assume we have POSIX strdup()
// (could just do *params = line; but
// line could now refer to a vary large buffer
// if a long comment line was in the file)
*params = strdup( line );
// tell the caller how long the line is
// (extraneous as it's a string, but...)
*ParamsLen = strlen( line );
free( line );
// found the line, so break the loop
break;
}
fclose( fp );
// didn't find a line that doesn't start with '#'
if ( *params == NULL )
{
return( -1 );
}
// success
return( 0 );
}
char *readParamFile( char* filename )
{
FILE *fp = fopen( filename, "r" );
if ( fp == NULL ) return( NULL );
unsigned char *line = NULL;
size_t lineLen = 0UL;
for ( ;; )
{
ssize_t bytesRead = getline( &line, &lineLen, fp );
if ( bytesRead == -1 ) break;
if ( line[ 0 ] == '#' ) continue;
line[ strcspn( "\n" ) ] = '\0';
break;
}
fclose( fp );
// oops! Don't return a comment line!
// could also strdup( line ) in loop above after finding proper line
if ( line != NULL && line[ 0 ] == '#' )
{
free( line );
line = NULL:
}
return( line );
}