使用 std::copy 复制数组时出现分段错误
Posted
技术标签:
【中文标题】使用 std::copy 复制数组时出现分段错误【英文标题】:getting segmentation fault when copying arrays using std::copy 【发布时间】:2019-05-08 16:36:53 【问题描述】:我正在尝试执行帕斯卡三角形,我需要将一个数组复制到另一个数组,我目前正在使用复制功能,但遇到了著名的分段错误。
这是我的代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
void print(const int *tab, const int &nbr)
for(int i = 0; i<nbr;i++)
cout << tab[i];
cout << endl;
int main()
int *tab;
int *tab1;
int index = 0;
cout << "enter a number less than or equal to 20!" << endl;
int number = 40;
while(number > 20)
cin >> number;
cout << endl;
int a = 1;
while(index < number)
tab[0] = 1;
for(int i=1;i<=index;i++)
tab[i] = i;
print(tab,index);
std::copy(tab,tab+index,tab1);
index++;
return 0;
我在使用 memcpy 函数时遇到了同样的错误,任何人都可以
【问题讨论】:
我建议您使用std::vector<int>
而不是原始指针。
@yes 目前尚不清楚您在 while 循环中要实现的目标。
想象你有一本电话簿,里面全是房子的地址……除了那些地段上没有任何房子,你告诉某人去那个地址的其中一间卧室睡觉。睡不着觉
您可以使用vector<int> tab = 1, 2, 3, 4, 5;
、std::array<int, 5> tab = 1, 2, 3 , 4, 5;
、int* tab = new int[5]1, 2, 3, 4, 5;
。我会建议向量,以便您可以执行 std::copy_n(tab.being(), index, tab1.begin());
或 std:copy(std::begin(tab), std::end(tab) + index, std::being(tab1));
或 std::copy_n(tab.being(), index, tab1.begin());
。毕竟,你在做C++
,而不是C
。
【参考方案1】:
(在您的版本之前)
使用 std::copy 复制数组时出现分段错误
问题出现在std::copy
之前
拥有
int *tab; int *tab1; ... tab[i] = tab1[i];
tab 和 tab1 未初始化,它们不指向用作数组的内存块,因此行为未定义(在您的情况下是分段错误) 每次被取消引用时
关于 number 的代码,您可能想要类似
int tab[20];
int tab1[20]
警告
for(int i=1;i<=index;i++)
您似乎认为数组的第一个索引是 1,而它是 0
您的代码中的一项建议(在您的版本之后)删除未定义的行为,更多其他更改,我评论了修改。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
void print(const int *tab, const int &nbr)
for(int i = 0; i<nbr;i++)
cout << tab[i] << ' '; // add a space to separate numbers
cout << endl;
int main()
int number;
do // your case it typically a "do while"
// print moved inside to clearly indicate the expected input
// even after a number invalid
// and also request a number > 0 else no sence after
cout << "enter a number between 1 and 20!" << endl;
if (!(cin >> number)) // detect the error else if a non number you loop forever
cerr << "invalid input" << endl;
cin.clear(); // clear the error
// bypass invalid input
string s;
if (! (cin >> s))
// EOF !
return -1;
number = 0; // to reloop
while ((number > 20) || (number <= 0));
int * tab = new int[number]; // added missing initialization
int * tab1 = new int[number]; // added missing initialization
for (int index = 0; index < number; ++index)
tab[0] = 1;
for(int i=1; i<=index; i++)
tab[i] = i;
print(tab,index);
std::copy(tab, tab+index, tab1);
// free resources
delete [] tab;
delete [] tab1;
return 0;
编译和执行:
pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -Wall cp.cc
pi@raspberrypi:/tmp $ ./a.out
enter a number between 1 and 20!
aze
invalid input
enter a number between 1 and 20!
-1
enter a number between 1 and 20!
21
enter a number between 1 and 20!
20
1
1 1
1 1 2
1 1 2 3
1 1 2 3 4
1 1 2 3 4 5
1 1 2 3 4 5 6
1 1 2 3 4 5 6 7
1 1 2 3 4 5 6 7 8
1 1 2 3 4 5 6 7 8 9
1 1 2 3 4 5 6 7 8 9 10
1 1 2 3 4 5 6 7 8 9 10 11
1 1 2 3 4 5 6 7 8 9 10 11 12
1 1 2 3 4 5 6 7 8 9 10 11 12 13
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
pi@raspberrypi:/tmp $
然而在
for (int index = 0; index < number; ++index) tab[0] = 1; for(int i=1; i<=index; i++) tab[i] = i; print(tab,index); std::copy(tab, tab+index, tab1);
tab被初始化了很多次都白费,每个条目只初始化一次就够了
std::copy(tab, tab+index, tab1);
没用,因为 tab1 从未使用过。
可以删除所有与 tab1 相关的内容,只保留:
tab[0] = 1;
for (int index = 1; index < number; ++index)
tab[index] = index;
print(tab,index);
在 valgrind 下执行以检查内存访问和泄漏(tab1 已删除):
pi@raspberrypi:/tmp $ valgrind ./a.out
==16633== Memcheck, a memory error detector
==16633== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16633== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16633== Command: ./a.out
==16633==
enter a number between 1 and 20!
10
1
1 1
1 1 2
1 1 2 3
1 1 2 3 4
1 1 2 3 4 5
1 1 2 3 4 5 6
1 1 2 3 4 5 6 7
1 1 2 3 4 5 6 7 8
==16633==
==16633== HEAP SUMMARY:
==16633== in use at exit: 0 bytes in 0 blocks
==16633== total heap usage: 4 allocs, 4 frees, 22,312 bytes allocated
==16633==
==16633== All heap blocks were freed -- no leaks are possible
==16633==
==16633== For counts of detected and suppressed errors, rerun with: -v
==16633== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
pi@raspberrypi:/tmp $
还请注意您错过了打印 print
中的最后一个元素for(int i = 0; i<nbr;i++)
可以
for(int i = 0; i<=nbr;i++)
【讨论】:
对不起,我编辑了我的帖子,标签已初始化,我想将其内容复制到 tab1。 @πάνταῥεῖ 但问题不是制表符,因为我可以通过调用打印函数打印其内容,问题是 tab1,tab1 被声明为指针,所以我可以这样做std::copy(tab,tab+index,tab1);
@lyes 好吧,未定义的行为是未定义,这意味着任何事情都可能发生。
@lyes 你错过了初始化它们,你明白这个问题吗?我想您想像我在回答中所说的那样拥有数组
@lyes 我用你的代码的更正版本编辑了我的答案(因为我能理解你想要什么)【参考方案2】:
我看到的问题:
在使用 tab
和 tab1
之前,您还没有为它们分配内存,就好像它们指向有效内存一样。这会导致未定义的行为。
您没有任何代码可以用数据填充tab
。没有这个,从tab
复制到tab1
是没有意义的。
更新后的代码初始化tab
。
【讨论】:
tab[0] 已初始化,只是忘记了这一行,这就是为什么我从 1 开始索引,数组被声明为指针,你的意思是我不能直接开始填充它? @lyes,是的,你可以。我错过了。以上是关于使用 std::copy 复制数组时出现分段错误的主要内容,如果未能解决你的问题,请参考以下文章