从结构指针内部打印字符串时输出错误 (VC++ 2010)
Wrong output when printing a string from inside a struct pointer (VC++ 2010)
我发现 printf(和 printf_s)和 std::cout 都有一个非常奇怪的问题。我不确定它是否缺少 "glitch" 或这些函数中的错误,或者我是否做错了什么。由于这两个函数的作用相同,我假设我没有以正确的方式进行操作。
我的程序中有以下结构(顺便说一句,这是一个Visual C++ 2010项目):
#pragma pack(push, 1)
typedef struct nameentry
{
char NAME[17];
char EXT[4];
}NAMEENTRY;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct fileentry
{
unsigned int ID;
NAMEENTRY FILENAME;
unsigned int GPFID;
unsigned long long int FPOINTER;
size_t FILESIZE;
}FILEENTRY;
#pragma pack(pop)
现在我有以下部分代码:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
printf("%s", myfile_->FILENAME.NAME);
所以这段代码应该做的是,创建一个 NAMEENTRY 的实例,其中 NAME=LONGFILE,EXT=JPG。两个字符数组都以 null 结尾(最后一个字节是 0)。然后使用我正在开发的数据库中的相应数据创建一个 FILEENTRY 实例,然后从 FILEENTRY 的 NAMEENTRY 结构中打印文件名。
在 运行 代码之后,我得到的不是文件名,而是...垃圾。尝试从坏指针打印文本时得到的经典垃圾。如果我尝试打印任何其他字段,我也会得到错误的值。
很明显,我的第一个想法是我的一个函数没有返回正确的值。所以我开始检查代码,令我惊讶的是,它们实际上返回了正确的值,并且结构中填充了正确的数据。我在每个字段中都得到了正确的值,每个字符数组都以 0 结尾,等等
然后我说..."What if I copy the entire block into another instance of FILEENTRY?",然后我尝试了这个:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
FILEENTRY dMem;
memcpy(&dMem, myfile_, sizeof(FILEENTRY));
printf("%s", dMem.FILENAME.NAME);
你猜怎么着?它工作得很好。我得到文件的名称,没有垃圾。所以我假设,问题出在 printf 内部(我也尝试 std::cout 得到相同的结果),或者我在使用这些函数时做错了。
嗯,这很有帮助。正如 Igor Tandetnik 所建议的,问题似乎是 return 指向局部变量的指针。
因此,作为一种解决方法,我不确定这是否是处理此问题的正确方法,我没有定义局部变量,而是使用 calloc 为 FILEENTRY 指针分配内存块,然后填充它和 return 它。是的,它似乎是这样工作的。
这是函数的实际代码:
FILEENTRY* SearchFileByPkgID(int ID, NAMEENTRY fname)
{
FILEENTRY* myFile = (FILEENTRY*)calloc(sizeof(FILEENTRY),1);
std::vector<int> results;
unsigned int* dptable = GetDPTableByPkgId(ID);
bool found = false;
for(int x = 0; x < 1024; x++)
{
if(dptable[x] > 0)
{
fseek(PDBFILE, dptable[x], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.EXT, fname.EXT) == 0)
if(myFile->FILENAME.NAME[0] == fname.NAME[0])
results.push_back(dptable[x]);
}
}
for(int y = 0; y < results.size(); y++)
{
fseek(PDBFILE, results[y], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.NAME, fname.NAME) == 0)
{
found = true;
break;
}
}
results.clear();
if(found)
return myFile;
else
return 0L;
}
欢迎大家多提建议
我发现 printf(和 printf_s)和 std::cout 都有一个非常奇怪的问题。我不确定它是否缺少 "glitch" 或这些函数中的错误,或者我是否做错了什么。由于这两个函数的作用相同,我假设我没有以正确的方式进行操作。
我的程序中有以下结构(顺便说一句,这是一个Visual C++ 2010项目):
#pragma pack(push, 1)
typedef struct nameentry
{
char NAME[17];
char EXT[4];
}NAMEENTRY;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct fileentry
{
unsigned int ID;
NAMEENTRY FILENAME;
unsigned int GPFID;
unsigned long long int FPOINTER;
size_t FILESIZE;
}FILEENTRY;
#pragma pack(pop)
现在我有以下部分代码:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
printf("%s", myfile_->FILENAME.NAME);
所以这段代码应该做的是,创建一个 NAMEENTRY 的实例,其中 NAME=LONGFILE,EXT=JPG。两个字符数组都以 null 结尾(最后一个字节是 0)。然后使用我正在开发的数据库中的相应数据创建一个 FILEENTRY 实例,然后从 FILEENTRY 的 NAMEENTRY 结构中打印文件名。
在 运行 代码之后,我得到的不是文件名,而是...垃圾。尝试从坏指针打印文本时得到的经典垃圾。如果我尝试打印任何其他字段,我也会得到错误的值。
很明显,我的第一个想法是我的一个函数没有返回正确的值。所以我开始检查代码,令我惊讶的是,它们实际上返回了正确的值,并且结构中填充了正确的数据。我在每个字段中都得到了正确的值,每个字符数组都以 0 结尾,等等
然后我说..."What if I copy the entire block into another instance of FILEENTRY?",然后我尝试了这个:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
FILEENTRY dMem;
memcpy(&dMem, myfile_, sizeof(FILEENTRY));
printf("%s", dMem.FILENAME.NAME);
你猜怎么着?它工作得很好。我得到文件的名称,没有垃圾。所以我假设,问题出在 printf 内部(我也尝试 std::cout 得到相同的结果),或者我在使用这些函数时做错了。
嗯,这很有帮助。正如 Igor Tandetnik 所建议的,问题似乎是 return 指向局部变量的指针。
因此,作为一种解决方法,我不确定这是否是处理此问题的正确方法,我没有定义局部变量,而是使用 calloc 为 FILEENTRY 指针分配内存块,然后填充它和 return 它。是的,它似乎是这样工作的。
这是函数的实际代码:
FILEENTRY* SearchFileByPkgID(int ID, NAMEENTRY fname)
{
FILEENTRY* myFile = (FILEENTRY*)calloc(sizeof(FILEENTRY),1);
std::vector<int> results;
unsigned int* dptable = GetDPTableByPkgId(ID);
bool found = false;
for(int x = 0; x < 1024; x++)
{
if(dptable[x] > 0)
{
fseek(PDBFILE, dptable[x], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.EXT, fname.EXT) == 0)
if(myFile->FILENAME.NAME[0] == fname.NAME[0])
results.push_back(dptable[x]);
}
}
for(int y = 0; y < results.size(); y++)
{
fseek(PDBFILE, results[y], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.NAME, fname.NAME) == 0)
{
found = true;
break;
}
}
results.clear();
if(found)
return myFile;
else
return 0L;
}
欢迎大家多提建议