Sorting in Fortran, Undefined Reference to Qsort_

Sorting in Fortran, undefined reference to qsort_

You would do better to put compare into a module and use it. This approach will allow the compiler to check for consistency between your call of the subroutine and its declaration. If the main program and the module are in the same file, put the module first.

module MySubs

contains

integer*2 function compar( a, b )
...
end function compar

end module MySubs

program trand

use MySubs
use SomeMod

....

end program trand

Where SomeMod is a module in another file SomeMod.f90 with the sorting routine qsort. Then compile and link:

gfortran SomeMod.f90 trand.f90

or whatever compiler and filenames you are using. The file with qsort needs to be before the file with program trand.

Skipping a part of the code according to command line arguement

I wouldn't use goto. I'd rather do something akin to the following

Logical :: sort_needed

sort_needed = .True.

... skip first part ...

ELSE IF (numargs.eq.2) THEN
CALL getarg(1,inputfile)
WRITE(*,*) ' Input: ',trim(inputfile)
CALL getarg(2,outputfile)
WRITE(*,*) 'Output: ',trim(outputfile)

sort_needed = .False.

ELSE
WRITE(*,*) '****** The input and output filenames are missing! ******'
CALL exit(0)
END IF

... skip to sort ....

If( sort_needed ) Then
Call sort( appropriate_arguments )
End If

...

End

In general avoid goto, it tends to lead to confusing code. While I'm not a zealot in modern Fortran it's very rarely the best way - in fact I honestly can't remember the last time I used it in anger

A few other things

1) This one is easy enough to follow but get into the habit of posting complete code, rather than fragments. More often than not it clarifies what you are trying to ask.

2) Bubble sort is a horribly inefficient algorithm. At least use something like selection sort as long as the files are not to big. However it is likely that something like a good quick or heap sort will save you lots of time in the long run

3) Fortran has standard ways of accessing the command line, and iargc and getarg are NOT the way of doing it. I suggest you look up and use command_argument_count and get_command_argument, any good, up to date Fortran book will cover these

calling a quick sort function with the comparison function as a parameter

cmp1 is really the best way. It should always perform correctly.

cmp2 is close. It would work most of the time, but if you are dealing with very large integers, the results would be wrong.

cmp3 is definitely not right. The values are actually ints, but are being treated as chars. The results would be meaningless.

C++ sort iteration sometimes gives wrong value

Your comparator does not provide a strict weak ordering. Specifically, if tour[i1] == tour[i2] there is a 50/50 chance that it will return true or false and the answer is not stable (it must be).

If your comparison function does not provide a strict weak ordering, the behaviour is undefined, and a seg-fault is one plausible behaviour.

I suggest using return i1 < i2; This will break the tie in a stable way.

Alternatively, there is no need to break the tie at all. Just use

[&tour](int i1, int i2) 
{
return tour[i1] < tour[i2];
}

std::sort is quite happy with a weak ordering; which means that both cmp(i1,i2) and cmp(i2,i1) may return false. What it can't cope with is them both returning true (or two calls with the same arguments returning different values.)

What is an undefined reference/unresolved external symbol error and how do I fix it in Fortran?

There are many possible ways you can see an error like this. You may see it when trying to build your program (link error) or when running it (load error). Unfortunately, there's rarely a simple way to see which cause of your error you have.

This answer provides a summary of and links to the other answers to help you navigate. You may need to read all answers to solve your problem.

The most common cause of getting a link error like this is that you haven't correctly specified external dependencies or do not put all parts of your code together correctly.

When trying to run your program you may have a missing or incompatible runtime library.

If building fails and you have specified external dependencies, you may have a programming error which means that the compiler is looking for the wrong thing.

Installing numpy under virtualenv python

you have to install python development packages:

  • in case Ubuntu or debian-based

sudo apt-get install python-dev build-essential

  • in case CentOS or RedHat based

yum install python-devel build-essential

Recommended way to track down array out-of-bound access/write in C program

What is the recommended way to make sure that every access or write to array (allocated on stack) is actually valid (i.e. not provoking undefined behaviour) ?

What if use clang on Linux with the options -fsanitize=addressand -fsanitize=undefined? It is also available in gcc: http://gcc.gnu.org/gcc-4.8/changes.html.



clang with the option -fsanitize=undefined

This is an example:

#include <stdlib.h>

#define N 5

int main(int argc, char *argv[])
{
int a[N] = {8, 1, 2, 3, 4}, i;

int r =0;
int end = atoi(argv[1]);
for (int i = 0; i != end; ++i)
r += a[i];

return r;
}

Then

clang -fno-omit-frame-pointer -fsanitize=undefined -g out_boundary.c -o out_boundary_clang

$ ./out_boundary_clang 5
$ ./out_boundary_clang 6
out_boundary.c:12:10: runtime error: index 5 out of bounds for type 'int [5]'
Illegal instruction (core dumped)

And then analyze a core file

Program terminated with signal 4, Illegal instruction.
#0 main (argc=2, argv=0x7fff3a1c28c8) at out_boundary.c:12
12 r += a[i];
(gdb) p i
$1 = 5



clang with the option -fsanitize=address

This is a quote:

The tool can detect the following types of bugs:

* Out-of-bounds accesses to heap, stack and globals
* Use-after-free
* Use-after-return (to some extent)
* Double-free, invalid free
* Memory leaks (experimental)

clang -fno-omit-frame-pointer -fsanitize=address -g out_boundary.c -o out_boundary_clang

And then:

$ ./out_boundary_clang 6 2>&1 | asan_symbolize.py
=================================================================
==9634==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff91bb2ad4 at pc 0x459c67 bp 0x7fff91bb2910 sp 0x7fff91bb2908
READ of size 4 at 0x7fff91bb2ad4 thread T0
#0 0x459c66 in main out_boundary.c:12
#1 0x3a1d81ed1c in __libc_start_main ??:0
#2 0x4594ac in _start ??:0
Address 0x7fff91bb2ad4 is located in stack of thread T0 at offset 244 in frame
#0 0x45957f in main out_boundary.c:6
This frame has 8 object(s):
[32, 36) ''
[96, 100) ''
[160, 168) ''
[224, 244) 'a'
[288, 292) 'i'
[352, 356) 'r'
[416, 420) 'end'
[480, 484) 'i1'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x10007236e500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007236e510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007236e520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007236e530: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x10007236e540: 04 f4 f4 f4 f2 f2 f2 f2 04 f4 f4 f4 f2 f2 f2 f2
=>0x10007236e550: 00 f4 f4 f4 f2 f2 f2 f2 00 00[04]f4 f2 f2 f2 f2
0x10007236e560: 04 f4 f4 f4 f2 f2 f2 f2 04 f4 f4 f4 f2 f2 f2 f2
0x10007236e570: 04 f4 f4 f4 f2 f2 f2 f2 04 f4 f4 f4 f3 f3 f3 f3
0x10007236e580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007236e590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007236e5a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==9634==ABORTING

Or you can use both this options. Useful links:

  • http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
  • http://developer.mozilla.org/en-US/docs/Mozilla/Testing/Firefox_and_Address_Sanitizer
  • http://clang.llvm.org/docs/AddressSanitizer.html


Related Topics



Leave a reply



Submit