0

私はこの非常に単純な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
4

6 に答える 6

10

アレイには自動保存期間があり、戻るareasとスコープから外れます。areaその場合、間接参照pointerは未定義の動作です。Cポインタの代わりにC++イディオムを使用してくださいstd::stringstd::vector

これがあなたのコードの改良された(しかしまだ最適ではない)バージョンです:

#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)
[…]

私のバージョンではエラーは発生しません。

于 2012-09-22T16:56:39.583 に答える
3

return pointer;-ローカル変数へのポインタを返しています。ローカル変数はスタックに割り当てられており、関数を終了するとスコープ外になります。

残念ながら、コンパイラはこれを認識するのに十分賢くありませんでした。たとえば、警告を受け取るためgccに戻る必要があります。areaswarning: address of local variable ‘areas’ returned

于 2012-09-22T17:00:05.327 に答える
2

C ++を初めて使用する場合は、新しい標準であるC++11を確認する必要があると思います。ウィキペディアのページから始めます。これは私のバージョンのコードです:

#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);   
}
于 2012-09-22T18:03:21.417 に答える
1

この関数から無効なメモリへのポインタを返しています。

int* area(char* radius[], int size)
{
        int* pointer;
        int areas[size];
        pointer = areas;

        // ...

        return pointer;
}

int areas[size]この機能の期間中のみ存在します。未定義のメモリへのポインタを返しています。

于 2012-09-22T17:01:06.417 に答える
0

半径は文字列「1」へのポインタですが、argc値をステップスルーしています。これは間違っています。

于 2012-09-22T17:01:49.270 に答える
0

これareasは整数ですが、floatを入れます。

正しい結果とは異なる可能性のある結果をもたらす半径を計算するとき!

areas[i] = 3.1416*atoi(radius[i])*atoi(radius[i]);

于 2012-09-22T16:57:04.753 に答える