Power & Source of Big Ideas

Division broken, Memory corrupted on Nano Pi Duo

Moderators: chensy, FATechsupport

Hi,

I noticed that the division of 64 bit integers is broken on Nano Pi Duo using the gcc and runtime lib from the Ubuntu repositories.

See the following example:

Code: Select all

#include <stdio.h>


unsigned long long int __udivmoddi4(unsigned long long int num, unsigned long long int den, unsigned long long int * rem_p)
{
    unsigned long long int quot = 0, qbit = 1;

    if (den == 0) {
      return 0;      /* If trap returns... */
    }

    /* Left-justify denominator and count shift */
    while ((signed long long int) den >= 0) {
   den <<= 1;
   qbit <<= 1;
    }

    while (qbit) {
   if (den <= num) {
       num -= den;
       quot += qbit;
   }
   den >>= 1;
   qbit >>= 1;
    }

    if (rem_p)
   *rem_p = num;

    return quot;
}

signed long long int div(signed long long int num, signed long long int den){
   bool signNum = num<0, signDen = den<0;
   signed long long int res = (signed long long int)__udivmoddi4((unsigned long long int)(signNum?-num:num), (unsigned long long int)(signDen?-den:den), NULL);
   return signNum!=signDen?-res:res;
}

int main(){

   signed long long int value1 = 999;
   signed long long int value2 = -333;
   value1 = value1 / value2;
   //value1 = div(value1, value2);
   
   printf("value1: %lli\n", value1);

   return 0;
}


You can test it with valgrind after compiling: valgrind --leak-check=yes ./test
If you use the custom div function (value1 = div(value1, value2);) everything works as expected but if you use the normal integer division (value1 = value1 / value2;) you get the following error:

Code: Select all

==2370== Memcheck, a memory error detector
==2370== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2370== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==2370== Command: ./test
==2370==
==2370== Invalid write of size 4
==2370==    at 0x4867B52: ??? (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2370==  Address 0xbde23430 is on thread 1's stack
==2370==  16 bytes below stack pointer
==2370==
==2370== Conditional jump or move depends on uninitialised value(s)
==2370==    at 0x48692FE: __udivmoddi4 (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2370==
==2370== Use of uninitialised value of size 4
==2370==    at 0x4869300: __udivmoddi4 (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2370==
==2370== Use of uninitialised value of size 4
==2370==    at 0x4867BA2: ??? (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2370==
value1: -3
==2370==
==2370== HEAP SUMMARY:
==2370==     in use at exit: 0 bytes in 0 blocks
==2370==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==2370==
==2370== All heap blocks were freed -- no leaks are possible
==2370==
==2370== For counts of detected and suppressed errors, rerun with: -v
==2370== Use --track-origins=yes to see where uninitialised values come from
==2370== ERROR SUMMARY: 5 errors from 4 contexts (suppressed: 6 from 3)


Please note: The mentioned __udivmoddi4 is from libgcc_s.so.1 and not from my code, so the error is clearly in the corresponding library. Feel free to comment out the whole replacement and see that the error still occurs.
Use the following compiler on an ubuntu 16.04 64bit host:
sudo apt-get -y install gcc-arm-linux-gnueabihf
sudo apt-get -y install g++-arm-linux-gnueabihf
Hi,

I'm not doing cross compiling. I have installed gcc on the Nano Pi Duo from the repositories.
(sudo apt-get install g++ directly on the NanoPi). I think this should be the correct compiler or am I wrong about that?

EDIT:
I have just tried it with the mentioned cross compiler and the result is the same.
I fear that the problem is in the shared object and therefore all program using 64 bit integer division on Nano Pi Duo are therefore unstable.
apt-get install -y gcc-4.8 g++-4.8
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 100

-----------------------------

root@NanoPi-NEO-Air:~# valgrind --leak-check=yes ./test.4.8
==1342== Memcheck, a memory error detector
==1342== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==1342== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==1342== Command: ./test.4.8
==1342==
value1: -3
==1342==
==1342== HEAP SUMMARY:
==1342== in use at exit: 0 bytes in 0 blocks
==1342== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==1342==
==1342== All heap blocks were freed -- no leaks are possible
==1342==
==1342== For counts of detected and suppressed errors, rerun with: -v
==1342== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
Thank you for your reply. Unfortunately the problem is not solved with gcc4.8 (see below).
I believe the problem is about the emulation of 64 bit integer division which is appearently not available in the 32 Bit ARMv7 architecture.
It seems to be however solved if it is compiled with optimization e.g. -O3, because the compiler can do the division in this particular test code at compile time.
If you compile it with -g, you can observe, that the problem still exists even with gcc4.8:

root@SensorBox:/home/pi/test# g++ --version
g++ (Ubuntu/Linaro 4.8.5-4ubuntu2) 4.8.5
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

root@SensorBox:/home/pi/test# g++ -g test.cpp -o test
root@SensorBox:/home/pi/test# valgrind --leak-check=yes ./test
==2446== Memcheck, a memory error detector
==2446== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2446== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==2446== Command: ./test
==2446==
==2446== Invalid write of size 4
==2446== at 0x4867B52: ??? (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2446== Address 0xbdccd438 is on thread 1's stack
==2446== 16 bytes below stack pointer
==2446==
==2446== Conditional jump or move depends on uninitialised value(s)
==2446== at 0x48692FE: __udivmoddi4 (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2446==
==2446== Use of uninitialised value of size 4
==2446== at 0x4869300: __udivmoddi4 (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2446==
==2446== Use of uninitialised value of size 4
==2446== at 0x4867BA2: ??? (in /lib/arm-linux-gnueabihf/libgcc_s.so.1)
==2446==
value1: -3
==2446==
==2446== HEAP SUMMARY:
==2446== in use at exit: 0 bytes in 0 blocks
==2446== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==2446==
==2446== All heap blocks were freed -- no leaks are possible
==2446==
==2446== For counts of detected and suppressed errors, rerun with: -v
==2446== Use --track-origins=yes to see where uninitialised values come from
==2446== ERROR SUMMARY: 5 errors from 4 contexts (suppressed: 6 from 3)

Who is online

In total there is 1 user online :: 0 registered, 0 hidden and 1 guest (based on users active over the past 5 minutes)
Most users ever online was 59 on Thu Aug 30, 2018 2:59 pm

Users browsing this forum: No registered users and 1 guest