[英]Why am I getting the following output?
我有這個非常簡單的c ++程序。 我做了一些C ++已經好幾年了,所以我想我可以再試試看一次。 但是我對獲得的輸出感到驚訝。 它本來應該是一個簡單的程序,已經使我有些頭疼。
//2.cpp
//This program asks for the radius of the circle and
//prints the area of that circle
#include <iostream>
#include <stdlib.h>
int* area(char* radius[], int size)
{
int* pointer;
int areas[size];
pointer = areas;
for(int i = 0; i < size; i++)
{
areas[i] = 3.1416*atoi(radius[i])*atoi(radius[i]);
}
return pointer;
}
void print(char* radius[], int* area1, int size)
{
std::cout<<area1[2]<<std::endl; //This prints fine
for(int i = 0; i < size; i++)
{
std::cout << area1[i]; //This doesn't
std::cout << "Area for " << radius[i] << " is: " << area1[i] << std::endl;
}
}
int main(int argc, char* argv[])
{
if(argc > 1)
{
print(&argv[1],area(&argv[1],argc-1),argc-1);
}
else
{
//Please ignore this
}
return 0;
}
輸入項
./a.out 1 4 2 7 8
輸出:-
12
134520896
Area for 1 is: 134520896
10
Area for 4 is: 10
-1217419175
Area for 2 is: -1217419175
-1217056780
Area for 7 is: -1217056780
-1217056780
Area for 8 is: -1217056780
您的areas
陣列具有自動存儲期限,一旦area
返回,它就會超出范圍。 那么取消引用pointer
是未定義的行為。 請使用諸如std::string
和std::vector
類的C ++習慣用法代替C指針。
這是代碼的改進版本(但仍不是最佳版本):
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstddef>
std::vector<double> area(const std::vector<double>& radius)
{
std::vector<double> areas(radius.size());
for (std::size_t i = 0; i < radius.size(); i++) {
areas[i] = 3.1416 * radius[i] * radius[i];
}
return areas;
}
void print(const std::vector<double>& radius, const std::vector<double>& area)
{
for (std::size_t i = 0; i < radius.size(); i++) {
std::cout << area[i]; //This doesn't
std::cout << "Area for " << radius[i] << " is: " << area[i] << std::endl;
}
}
int main(int argc, char* argv[])
{
if (argc > 1) {
std::vector<double> radii;
radii.reserve(argc - 1);
for (int i = 1; i < argc; ++i) {
radii.push_back(std::atof(argv[i]));
}
print(radii, area(radii));
}
}
不幸的是,編譯器通常無法檢測到此類錯誤。 使用Valgrind之類的工具來查找它們。 例如,通過Valgrind運行您的原始代碼會對我產生許多錯誤:
$ valgrind ./a.out 1 4 2 7 8
==18488== Memcheck, a memory error detector
==18488== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==18488== Using Valgrind-3.8.0 and LibVEX; rerun with -h for copyright info
==18488== Command: ./a.out 1 4 2 7 8
==18488==
==18488== Conditional jump or move depends on uninitialised value(s)
==18488== at 0x4EC5D16: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.17)
==18488== by 0x4EC5F4C: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.17)
==18488== by 0x4EC8E45: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/libstdc++.so.6.0.17)
==18488== by 0x400A01: print(char**, int*, int) (in /tmp/a.out)
==18488== by 0x400B0E: main (in /tmp/a.out)
==18488==
==18488== Use of uninitialised value of size 8
==18488== at 0x4EBB133: ??? (in /usr/lib/libstdc++.so.6.0.17)
==18488== by 0x4EC5D37: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.17)
==18488== by 0x4EC5F4C: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.17)
==18488== by 0x4EC8E45: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/libstdc++.so.6.0.17)
==18488== by 0x400A01: print(char**, int*, int) (in /tmp/a.out)
==18488== by 0x400B0E: main (in /tmp/a.out)
[…]
而我的版本沒有錯誤。
return pointer;
-您將返回指向局部變量的指針,該局部變量在堆棧中分配,並且在退出函數時超出范圍。
不幸的是,您的編譯器不夠聰明,無法識別這一點,例如在gcc
我必須返回areas
以獲取警告: warning: address of local variable 'areas' returned
如果您從C ++重新開始,我認為您應該看看新標准C ++ 11 。 從Wikipedia頁面開始。 這是我的代碼版本:
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
std::vector<double> area(const std::vector<double> & radii ) {
std::vector<double> areas(radii.size());
std::transform (radii.begin(), radii.end(), areas.begin(),
[](const double &r){ return 3.15159*r*r; } );
return areas;
}
void printit(const std::vector<double> &r, const std::vector<double> &a) {
for(size_t i = 0; i < r.size(); ++i) {
std::cout << "Area for " << r.at(i) << " is: " << a.at(i) << std::endl;
}
}
int main(int argc, char* argv[]) {
std::vector<double> r(argc-1);
std::transform (argv+1, argv+argc,r.begin(),
[](const std::string &r){ return stod(r); } );
auto areas=area(r);
printit(r,areas);
}
您正在從該函數返回一個指向無效內存的指針。
int* area(char* radius[], int size)
{
int* pointer;
int areas[size];
pointer = areas;
// ...
return pointer;
}
int areas[size]
僅在此功能期間存在。 您正在返回一個指向未定義內存的指針。
這些areas
是整數,但您將浮點數放入其中。
計算半徑時,得出的結果可能與正確的結果不同!
areas[i] = 3.1416*atoi(radius[i])*atoi(radius[i]);
Radius是指向字符串“ 1”的指針,但是您正在逐步遍歷argc值,這是錯誤的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.