我正在创建一个返回指向wchar_t的指针的函数,但每次使用它时都不会返回任何内容。
功能:
wchar_t *Character::getCharHealth() {
wchar_t charHealth[256];
swprintf_s(charHealth, L"%d", this->getHealth());
wprintf(L"%s\n", charHealth);
wchar_t* cHealth = charHealth;
return cHealth;
}
getHealth()函数:
int Character::getHealth() {
return this->health;
}
使用它的地方:
spriteFont->DrawString(spriteBatch.get(), warrior->getCharHealth(), DirectX::SimpleMath::Vector2(40, 0));
我的代码有什么问题吗?
答案 0 :(得分:2)
cHealth
是指向charHealth
的指针,getCharHealth
是charHealth
函数的本地指针。函数返回后,cHealth
使用的内存将被释放,因此charHealth
是一个野指针。一种可能的解决方案是使用new
在堆上为class Program
{
static void Main(String[] args)
{
Console.WriteLine(RoundAndFormat(1));
Console.WriteLine(RoundAndFormat(10));
Console.WriteLine(RoundAndFormat(100));
Console.WriteLine(RoundAndFormat(1000));
Console.WriteLine(RoundAndFormat(100000));
Console.WriteLine(RoundAndFormat(125000));
Console.WriteLine(RoundAndFormat(125900));
Console.WriteLine(RoundAndFormat(1000000));
Console.WriteLine(RoundAndFormat(1250000));
Console.WriteLine(RoundAndFormat(1258000));
Console.WriteLine(RoundAndFormat(10000000));
Console.WriteLine(RoundAndFormat(10500000));
Console.WriteLine(RoundAndFormat(100000000));
Console.WriteLine(RoundAndFormat(100100000));
Console.ReadLine();
}
public static String RoundAndFormat(Int32 value)
{
var result = String.Empty;
var negative = value < 0;
if (negative) value = value * -1;
if (value < 1000)
{
result = value.ToString();
}
else if (value < 1000000)
{
result = RoundDown(value / 1000.0, 0) + "K";
}
else if (value < 100000000)
{
result = RoundDown(value / 1000000.0, 2) + "M";
}
else if (value < 10000000000)
{
result = RoundDown(value / 1000000.0, 0) + "M";
}
if (negative) return "-" + result;
return result;
}
public static Double RoundDown(Double value, Int32 digits)
{
var pow = Math.Pow(10, digits);
return Math.Truncate(value * pow) / pow;
}
分配空间。
答案 1 :(得分:1)
问题是您正在尝试返回wchar_t charHealth[256];
但是,这是一个局部变量,在函数结束时被销毁。虽然您可以使用其地址,但一旦退出该功能就没有任何意义,这就是您无法使用该返回的原因。
如果要返回在函数中创建的数组,则需要使用new
明确分配它:
wchar_t *charHealth = new wchar_t[256];
答案 2 :(得分:1)
您正在返回指向已超出范围的数组的指针,wchar_t charHealth[256]
一旦完成运行就属于getCharHealth()
&#39 ; s未定义的行为,以再次访问charHealth
数组。
您可以尝试为charHealth
分配动态缓冲区,然后返回:
wchar_t *Character::getCharHealth() {
wchar_t* charHealth = new wchar_t[256];
swprintf_s(charHealth, L"%d", this->getHealth());
wprintf(L"%s\n", charHealth);
return charHealth;
}
然后必须在不再需要时记得delete[]
:
wchar_t* cHealth = warrior->getCharHealth();
spriteFont->DrawString(spriteBatch.get(), cHealth, DirectX::SimpleMath::Vector2(40, 0));
delete[] cHealth;
您很容易忘记delete[]
。相反,您可以使用std::unique_ptr<wchar_t[]>
自动删除销毁时的指针。如果您不熟悉,这是一种名为RAII的技术。
但实际上,您可能应该使用std::wstring
和std::to_wstring
将数字从int
转换为std::wstring
,因为这样的对象包含正确的字符串存储优化和需要照顾可能需要的任何分配。
std::wstring Character::getCharHealth() {
std::wstring charHealth = std::to_wstring(this->getHealth());
wprintf(L"%s\n", charHealth.c_str());
return charHealth;
}
要从std::wstring
访问原始const wchar_t*
,您应该使用.c_str()
方法,如下所示:
spriteFont->DrawString(spriteBatch.get(), warrior->getCharHealth().c_str(), DirectX::SimpleMath::Vector2(40, 0));
答案 3 :(得分:0)
这是由返回堆栈上的本地分配数组引起的。函数Character::getCharHealth
返回后,程序将覆盖内存空间。
您的gcc
或clang
编译器应为此输出警告消息,仔细检查这些消息可以节省大量时间。
对于clang,警告由标记-Wreturn-stack-address
控制,默认情况下已打开。对于gcc,警告由标记-Wreturn-local-addr
控制,默认情况下也会打开。