gpt4 book ai didi

c++ - 可能的编译器错误,本地结构从模板参数访问函数中的静态变量(phew)

转载 作者:太空狗 更新时间:2023-10-29 21:46:33 25 4
gpt4 key购买 nike

如果标记行被注释掉,有人可以解释为什么以下代码在 Visual Studio C++ 2008/2010 上不起作用吗?是编译器错误还是我做错了什么?该代码应输出 10 个 U 的序列,但删除该行后,它什么也不输出。变量 chr 在 FilledArray 构造函数中变为 0。谢谢!

// returns a c-string which contains the char repeated a certain number of times
template<char THE_CHAR>
const char *RepeatChar(unsigned int uiNumber)
{
// must be static so can be accessed by struct
static const unsigned int uiMaxSize = 1024;
static const char chr = THE_CHAR;
char temp = chr; // comment out this line and it doesn't work

assert(uiMaxSize > 0);
assert(uiNumber <= uiMaxSize);

static const struct FilledArray
{
char data[uiMaxSize + 1];

FilledArray()
{
// fill all but last with the char (space for terminator)
fill(data, data + uiMaxSize, chr);
data[uiMaxSize] = '\0';
}

} sFilledArray;

// clever bit
return sFilledArray.data + uiMaxSize - uiNumber;
}

int main()
{
cout << RepeatChar<'U'>(10) << endl;
}

最佳答案

看起来像是一个编译器错误。我将代码更改为以下内容:

#include <iostream>
#include <assert.h>
using namespace std;

// returns a c-string which contains the char repeated a certain number of times
template<char THE_CHAR>
const char *RepeatChar(unsigned int uiNumber)
{
// must be static so can be accessed by struct
static const unsigned int uiMaxSize = 1024;
static const char chr = THE_CHAR;
// char temp = chr; // comment out this line and it doesn't work

static const struct FilledArray
{
char data[uiMaxSize + 1];

FilledArray()
{
cout << "[" << chr << "]" << endl;
fill(data, data + uiMaxSize, chr);
data[uiMaxSize] = '\0';
}

} sFilledArray;

return sFilledArray.data + uiMaxSize - uiNumber;
}

int main()
{
cout << RepeatChar<'U'>(10) << endl;
}

然后对问题区进行拆解,即:

cout << "[" << chr << "]" << endl;
fill(data, data + uiMaxSize, chr);
data[uiMaxSize] = '\0';

和:

            cout << "[" << chr << "]" << endl;
00FA3273 push offset std::endl (0F9E730h)
00FA3278 push offset string "]" (0FFE3C0h)
00FA327D push 55h
00FA327F push offset string "[" (0FFE3BCh)
00FA3284 push offset std::cout (1011F80h)
00FA3289 call std::operator<<<std::char_traits<char> > (0F9EF91h)
00FA328E add esp,8
00FA3291 push eax
00FA3292 call std::operator<<<std::char_traits<char> > (0F9FA3Bh)
00FA3297 add esp,8
00FA329A push eax
00FA329B call std::operator<<<std::char_traits<char> > (0F9EF91h)
00FA32A0 add esp,8
00FA32A3 mov ecx,eax
00FA32A5 call std::basic_ostream<char,std::char_traits<char> >::operator<< (0F9EFD2h)
fill(data, data + uiMaxSize, chr);
00FA32AA push offset `RepeatChar<85>'::`2'::chr (0FFE3BAh)
00FA32AF mov eax,dword ptr [this]
00FA32B2 add eax,400h
00FA32B7 push eax
00FA32B8 mov ecx,dword ptr [this]
00FA32BB push ecx
00FA32BC call std::fill<char *,char> (0F9E839h)
00FA32C1 add esp,0Ch
data[uiMaxSize] = '\0';
00FA32C4 mov eax,dword ptr [this]
00FA32C7 mov byte ptr [eax+400h],0

请注意,当 cout << 使用时,它会显式替换字符 (55h) 来代替 chr:

00FA327D  push        55h  

但是,当用作 fill 的参数时,它使用 offset RepeatChar<85>':: 2'::chr (0FFE3BAh) 如:

00FA32AA  push        offset `RepeatChar<85>'::`2'::chr (0FFE3BAh)  

但内存位置 0FFE3BAh 包含一个 0。但是如果 chr 在其他地方使用,则它会在该位置填充 55h。

看起来生成静态部分的代码认为它已经完全优化了 chr,但实际上并没有。

不幸的是,我们没有 VC++ 的源代码,因此在 Microsoft 修复它之前,这仍然是个谜。

编辑:

相同的代码无法在 g++ 4.4.5 中编译。好吧,它实际上编译得很好,但是生成的代码依赖于它似乎遗漏的外部,这导致链接器 barf。使用 g++ 编译时出现以下错误代码:

/tmp/cccGJmv9.o: In function `char const* RepeatChar<(char)85>(unsigned int)::FilledArray::FilledArray()':
b1.cpp:(.text+0x56): undefined reference to `chr'
b1.cpp:(.text+0xa5): undefined reference to `uiMaxSize'
b1.cpp:(.text+0xb2): undefined reference to `chr'
b1.cpp:(.text+0xc1): undefined reference to `uiMaxSize'
collect2: ld returned 1 exit status

这与诊断一致,它似乎认为它优化了静态常量变量,但实际上并没有。

关于c++ - 可能的编译器错误,本地结构从模板参数访问函数中的静态变量(phew),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14855156/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com