Skillnad mellan 32 och 64 bitars C++ kompilator

Permalänk

Skillnad mellan 32 och 64 bitars C++ kompilator

Denna kod för nearest neighbour funkar bra på RPi3 (32bitar) men ger segmentation fault med x86_64 (g++ 9.2.1).
Några tips?

#include<iostream>
using namespace std;

int c = 0, cost = 1000;
int g[3][3] = { {1,2,3},{4,5,8},{6,7,10}};

void swap(int *x, int *y) {
int t;
t = *x;
*x = *y;
*y = t;
}

void cal_sum(int *a, int n) {
int i, s= 0;
for (i = 0; i <= n; i++) {
s+= g[a[i %3]][a[(i+ 1) %3]];
}
if (cost >s) {
cost = s;
}
}

void permute(int *a,int i,int n) {
int j, k;
if (i == n) {
cal_sum (a,n);
} else {
for (j = i; j <= n; j++) {
swap((a + i), (a + j));
cal_sum(a+1,n);
swap((a + i), (a + j));
}
}
}

int main() {
int i, j;
int a[] = {1,2,3};//take array elements
permute(a, 0,2);
cout << "minimum cost:" << cost << endl;
}

Permalänk
Medlem

I permute så anropar du cal_sum(a + 1, n), vilket innebär att a i cal_sum representerar en array med två element ({2, 3}). I cal_sum så indexerar du sedan arrayen med a[(i+ 1) %3] vilket blir a[2] när i == 1. Programmet försöker alltså läsa data utanför arrayen vilket resulterar i odefinierat beteende, så att det "fungerar" på din RPi3 är bara otur (bättre att programmet kraschar i såna här fall, annars kanske du får ett felaktigt resultat som du tror är rätt).

Du kan lätt hitta såna här fel med valgrind för övrigt, bara kompilera med -g för att få med debuginfo i programmet och kör valgrind ./programmets_namn. I mitt fall fick jag då:

==181963== Use of uninitialised value of size 8 ==181963== at 0x10926C: cal_sum(int*, int) (main.cpp:17) ==181963== by 0x10931E: permute(int*, int, int) (main.cpp:32) ==181963== by 0x1093A8: main (main.cpp:41)

D.v.s. programmet försöker använda ett oinitialiserat värde, där felet uppstår i cal_sum men värdet kommer ursprungligen från main (rad-nummret pekar på deklarationen av a i main).

Permalänk
Datavetare

Då du ändå använder en C++ kompilator finns en sak till du kan börja använda som i detta fall fångat problemet @perost pekar ut redan vid kompilering. Finns även två out-of-bounds buggar till som med användning av hittas vid runtime om man skriver om ditt program så här

#include <array> #include <iostream> #include <utility> typedef std::array<int, 3> vec_t; int c = 0; int cost = 1000; std::array<vec_t, 3> g{ vec_t{ 1, 2, 3 }, vec_t{ 4, 5, 8 }, vec_t{ 6, 7, 10 } }; void cal_sum(vec_t &a, int n) { int i, s= 0; for (i = 0; i <= n; i++) { // std::array<> at() method will throw "out-of-bounds" error here s += g.at(a[i % 3]).at(a[(i + 1) % 3]); // above is the same as this with the overhead of bounds-check // s += g[a[i % 3]][a[(i + 1) % 3]]; } if (cost > s) { cost = s; } } void permute(vec_t &a, int i, int n) { int j, k; if (i == n) { cal_sum(a, n); } else { for (j = i; j <= n; j++) { // swapping two elements in an array is a standard function in C++ std::swap(a[i], a[j]); //cal_sum(a+1,n); <- doesn't even compile when using std::array<>! cal_sum(a,n); std::swap(a[i], a[j]); } } } int main() { int i, j; // elements of 'a' is used to index into 'g', so value '3' will cause // out-of-bounds vec_t a{1,2,3}; //take array elements permute(a, 0, 2); std::printf("minium cost: %d\n", cost); }

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk

Uppdatering

Tack för svaren!
Ja det verkar handla om att gcc för Raspberry Pi är ovanligt förlåtande.
För x86 ser det om som om 64 bitars gcc uppdateras men inte 32 bitars gcc längre.