【发布时间】:2021-03-26 14:25:25
【问题描述】:
我的输入测试用例文件中的值使得在代码中的某个点,值会超过 int 的容量,所以我想我应该将这个值大于 INT_MAX 的特定数组的数据类型从 int 更改为long long 并将代码中的最大值从 INT_MAX 更改为 LLONG_MAX,以便运行时的比较不会产生错误的答案。
然而,现在代码似乎在到达上述测试用例之前就陷入了运行时错误。它现在在值都是面向 int 时过去通过的情况下失败。我不明白这怎么可能。
int 通过但 ll 失败的测试用例是:
100 50
1 23 133
1 87 16
2 9 78
3 12 117
3 39 19
5 25 219
5 47 130
5 97 157
6 50 114
9 11 25
9 39 227
10 45 187
10 77 120
12 19 85
13 43 247
14 16 4
15 33 223
16 33 1
19 69 204
20 35 119
20 43 213
20 86 19
22 40 233
23 33 61
23 79 152
26 89 213
27 57 129
28 42 220
31 68 84
31 69 183
32 39 145
32 100 117
33 49 198
34 48 78
37 66 200
37 91 77
39 44 235
41 70 109
42 92 33
44 74 196
48 73 26
51 57 216
53 70 158
63 98 220
66 72 148
80 93 150
81 99 54
83 84 129
83 89 177
95 100 16
下面是在这个 tc 处给出错误的代码。
#include<bits/stdc++.h>
using namespace std;
# define ll long long int
ll update, previous;
set<pair<ll, int>> dist;
auto it=dist.begin();
int ind=0, n, i, j;
pair<ll, int>p;
void dij(vector<pair<int, ll>> tree[], bool decided[], ll d[], int path[]) {
ind=0;
while(!dist.empty()) {
it=dist.begin();
if(it==dist.end()) return;
ind=it->second;
dist.erase(it);
decided[ind]=1;
for(j=0; j<tree[ind].size(); j++) {
update=d[ind]+tree[ind][j].second;
previous=d[tree[ind][j].first];
if(update<previous) {
p=make_pair(previous, tree[ind][j].first);
dist.erase(dist.find(p));
p=make_pair(update, tree[ind][j].first);
dist.insert(p);
path[tree[ind][j].first]=ind;
}
d[tree[ind][j].first]=min(update, previous);
}
}
}
int main()
{
ll edges;
ll x, y, weight;
cin>>n>>edges;
vector<pair<int, ll>> graph[n];
for(i=0; i<edges; i++) {
cin>>x>>y>>weight;
x--; y--;
graph[x].push_back({y, weight});
graph[y].push_back({x, weight});
}
int src=1;
src--;
ll d[n];
for(i=0; i<n; i++) {
if(src==i) {
dist.insert({0, i});
d[i]=0;
}
else {
dist.insert({LLONG_MAX, i});
d[i]=LLONG_MAX;
}
}
bool decided[n]={0};
int path[n]={-1};
for(int i=1; i<n; i++) path[i]=-2;
dij(graph, decided, d, path);
if(path[n-1]==-2) cout<<-1;
else {
vector<int> s;
int final=n-1;
while (final!=-1) {
s.push_back(final);
final=path[final];
}
reverse(s.begin(), s.end());
for(auto pi:s) cout<<pi+1<<" ";
}
cout<<endl;
}
下面是为这个 tc 生成正确输出的代码。
#include<bits/stdc++.h>
using namespace std;
# define ll long long int
ll update, previous;
set<pair<ll, int>> dist;
auto it=dist.begin();
int ind=0, n, i, j;
pair<ll, int>p;
void dij(vector<pair<int, ll>> tree[], bool decided[], int d[], int path[]) {
ind=0;
while(!dist.empty()) {
it=dist.begin();
if(it==dist.end()) return;
ind=it->second;
dist.erase(it);
decided[ind]=1;
for(j=0; j<tree[ind].size(); j++) {
update=d[ind]+tree[ind][j].second;
previous=d[tree[ind][j].first];
if(update<previous) {
p=make_pair(previous, tree[ind][j].first);
dist.erase(dist.find(p));
p=make_pair(update, tree[ind][j].first);
dist.insert(p);
path[tree[ind][j].first]=ind;
}
d[tree[ind][j].first]=min(update, previous);
}
}
}
int main()
{
ll edges;
ll x, y, weight;
cin>>n>>edges;
vector<pair<int, ll>> graph[n];
for(i=0; i<edges; i++) {
cin>>x>>y>>weight;
x--; y--;
graph[x].push_back({y, weight});
graph[y].push_back({x, weight});
}
int src=1;
src--;
int d[n];
for(i=0; i<n; i++) {
if(src==i) {
dist.insert({0, i});
d[i]=0;
}
else {
dist.insert({INT_MAX, i});
d[i]=INT_MAX;
}
}
bool decided[n]={0};
int path[n]={-1};
for(int i=1; i<n; i++) path[i]=-2;
dij(graph, decided, d, path);
if(path[n-1]==-2) cout<<-1;
else {
vector<int> s;
int final=n-1;
while (final!=-1) {
s.push_back(final);
final=path[final];
}
reverse(s.begin(), s.end());
for(auto pi:s) cout<<pi+1<<" ";
}
cout<<endl;
}
这两个代码的唯一区别是以下几行:
void dij(vector
> tree[], bool denied[], ll d[], int path[]) void dij(vector
> tree[], bool denied[], int d[], int path[])
ll d[n];
int d[n];
dist.insert({LLONG_MAX, i})
dist.insert({INT_MAX, i})
d[i]=LLONG_MAX
d[i]=INT_MAX
有人可以指出这是如何产生以下错误,我读到的错误与“在我不应该分配内存的地方”或“尝试使用不是从 new 获得的指针值执行删除”有关。是什么导致了这个问题,我应该如何解决?
free(): invalid pointer
Aborted (core dumped)
【问题讨论】:
-
既然知道
std::vector,为什么还要使用非标准且有风险的变长数组? -
int d[n];-- 补充一下前面的评论,你已经在使用std::vector,那你为什么不在这里也使用它呢?您似乎不知道向量的用途。 -
用向量代替数组能解决问题吗?
-
使用向量会给你一个解决问题的机会。使用矢量,您可以使用
at()函数来测试边界条件。对于那些非标准的可变长度数组,没有这样的东西。无论如何,任何使用 Visual C++ 来尝试测试您的代码的人都必须更改它。如果您将代码更改为不使用任何 VLA 并使用向量会更好。 -
欢迎来到 C++ 的世界。仅仅因为代码“有效”并不意味着它是正确的。 C++ 有一种叫做“未定义行为”的东西。
标签: c++ pointers integer runtime-error long-long