Skip to content

Hashtable write error on exit #750

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
chuckyvt opened this issue Dec 5, 2023 · 7 comments
Closed

Hashtable write error on exit #750

chuckyvt opened this issue Dec 5, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@chuckyvt
Copy link
Contributor

chuckyvt commented Dec 5, 2023

Description

I am running into a write access violation with the hashmap function when it goes out of scope. This typically happens only with relatively large maps, in the attached example code, 1020000 entries works, but 1030000 fails. My guess is it is an error is in the "final" procedure to free memory. If the hashmap is in the main program scope, I typically don't see the error. My understanding is the final procedure won't be called at the main program scope level.

Example code:

program hash_error

use stdlib_hashmaps, only: chaining_hashmap_type, open_hashmap_type
use stdlib_hashmap_wrappers, only: fnv_1_hasher, key_type, set
    
implicit none
 
call hash_test

contains

subroutine hash_test
    
    character(len=12) :: char_key
    
    integer :: i, n

    type(key_type) :: key
    type(chaining_hashmap_type) :: test_map
    
    ! 1020000 works
    ! 1030000 fails
    n=1030000
    
    call test_map%init(fnv_1_hasher, 22)

    do i = 1, n

        write (char_key,'(I0)') i
        call set(key, char_key )
            
        call test_map%map_entry(key)

    enddo
    
end subroutine hash_test

end program

Expected Behaviour

Intent would be for the subroutine to exit without error.

Version of stdlib

0.3.0

Platform and Architecture

Windows, Intel IFX and IFort compiler v2024.0, GFortran 13.2

Additional Information

No response

@chuckyvt chuckyvt added the bug Something isn't working label Dec 5, 2023
@chuckyvt
Copy link
Contributor Author

chuckyvt commented Dec 5, 2023

recursive subroutine free_map_entry_pool(pool) seems to be the free memory routine that is causing the error.

@jvdp1
Copy link
Member

jvdp1 commented Dec 25, 2023

Thank you @chuckyvt for reporting the issue.

I used ifx 2024.0.2 and I could not run even the following simple program:

program main

use stdlib_hashmaps, only: chaining_hashmap_type
use stdlib_hashmap_wrappers, only: fnv_1_hasher
    
implicit none
 
call hash_test

contains

subroutine hash_test
    
    type(chaining_hashmap_type) :: map
    
    call map%init(fnv_1_hasher)
    
end subroutine hash_test

end program main

I got the following error on my Fedora computer:

$ fpm run
Project is up to date
==226944==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x4aaed7 in stdlib_hashmaps_MP_init_chaining_map_ /home/jvandenp/test_hash/build/dependencies/stdlib/src/stdlib_hashmap_chaining.f90:472:9
    #1 0x48b0c3 in main_IP_hash_test_ /home/jvandenp/test_hash/app/main.f90:16:10
    #2 0x489cf3 in MAIN__ /home/jvandenp/test_hash/app/main.f90:8:6
    #3 0x40a5c8 in main (/home/jvandenp/test_hash/build/ifx_22B6DB2C5432A52F/app/test_hash+0x40a5c8) (BuildId: e27a311375dcefa55955a7499cd17857dcbbaed4)
    #4 0x7ffa4822950f in __libc_start_call_main (/lib64/libc.so.6+0x2950f) (BuildId: 8257ee907646e9b057197533d1e4ac8ede7a9c5c)
    #5 0x7ffa482295c8 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x295c8) (BuildId: 8257ee907646e9b057197533d1e4ac8ede7a9c5c)
    #6 0x40a494 in _start (/home/jvandenp/test_hash/build/ifx_22B6DB2C5432A52F/app/test_hash+0x40a494) (BuildId: e27a311375dcefa55955a7499cd17857dcbbaed4)

  Uninitialized value was created by an allocation of 'var$66' in the stack frame
    #0 0x4a6ccb in stdlib_hashmaps_MP_init_chaining_map_ /home/jvandenp/test_hash/build/dependencies/stdlib/src/stdlib_hashmap_chaining.f90:417:42

SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/jvandenp/test_hash/build/dependencies/stdlib/src/stdlib_hashmap_chaining.f90:472:9 in stdlib_hashmaps_MP_init_chaining_map_
Exiting
<ERROR> Execution for object " test_hash " returned exit code  1
<ERROR> *cmd_run*:stopping due to failed executions
STOP 1

Could you test it on your computer, please?
I am wondering if it is not a bug of the compiler itself.

@jvdp1
Copy link
Member

jvdp1 commented Dec 25, 2023

Update: it seems to be a more general issue: see here for more details.

@chuckyvt
Copy link
Contributor Author

Interesting. I'm on Windows, and I believe IFX for Linux has more detailed memory sanitizer features, so I am not seeing this. I will say I have tested the posted code snippet with IFX, IFort, and GFortran 13.2 and see the same behavior for all. So at this point, it doesn't seem to be compiler specific.

@jvdp1
Copy link
Member

jvdp1 commented Dec 25, 2023

Strange. I can compile and run the posted code snippet with GCC 12.2.1. on my Fedora computer.

Do you have similar problems with the stdlib tests or examples? All of them are tested with GCC 13 in the CI (Linux and Windows).

@chuckyvt
Copy link
Contributor Author

chuckyvt commented Jan 4, 2024

Ok, so I think I have this run to ground. Long story short, the failure is due to a stack overflow as best I can tell, though the program doesn't say that. (Just returns a memory access error vs a specific stack overflow message I'm used to). This would explain the different behavior between Linux and Windows. I have increased the stack size and now runs ok.

As a side note, since on the stdlib test cases the hashtable is at the main program level, the final procedure is never called in the checks I put together. Structuring a test case so that the hastable is in a subroutine or similar may be a decent idea to include at some point.

@chuckyvt chuckyvt closed this as completed Jan 4, 2024
@jvdp1
Copy link
Member

jvdp1 commented Jan 7, 2024

Thank you @chuckyvt for clarifying and closing the issue.

As a side note, since on the stdlib test cases the hashtable is at the main program level, the final procedure is never called in the checks I put together. Structuring a test case so that the hastable is in a subroutine or similar may be a decent idea to include at some point.

Good point. Don't hesitate to submit a PR with such a test. Otherwise I'll try to do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants