LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-04-2012, 08:53 PM   #1
trist007
Senior Member
 
Registered: May 2008
Distribution: Slackware
Posts: 1,052

Rep: Reputation: 70
I don't understand how this element in an int array gets assigned here...


This is in C
Code:
else if (cache_index == 255) {
  n = replace_array[cache_index];
  cache_array[((cache_index * assoc) + assoc) + n] = cache_tag;
}
Here is what gdb says
Code:
Hardware watchpoint 2: replace_array[0]

Old value = 0
New value = 241478
0x080493fe in main (argc=6, argv=0xbf9b95e4) at cache_sim.c:425
425								cache_array[((cache_index * assoc) + assoc) + n] = cache_tag;
(gdb) print replace_array[0]
$2 = 241478
I don't make any assignment for replace_array[0](cache_index == 0). The value of 241478 is what cache_tag is assigned to. Is this some sort of overflow?

-Tristan

Last edited by trist007; 11-04-2012 at 08:58 PM.
 
Old 11-04-2012, 09:13 PM   #2
trist007
Senior Member
 
Registered: May 2008
Distribution: Slackware
Posts: 1,052

Original Poster
Rep: Reputation: 70
Here's the output of valgrind, in case it'll shed some light.
Code:
root@ariel:~625> valgrind -v ./cache_sim 32 32 4 sample5.in sick
==11984== Memcheck, a memory error detector
==11984== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==11984== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==11984== Command: ./cache_sim 32 32 4 sample5.in sick
==11984== 
--11984-- Valgrind options:
--11984--    -v
--11984-- Contents of /proc/version:
--11984--   Linux version 2.6.37.3-smpx (root@ariel) (gcc version 4.3.3 (GCC) ) #1 SMP PREEMPT Thu Oct 25 21:37:21 CDT 2012
--11984-- Arch and hwcaps: X86, x86-sse1-sse2
--11984-- Page sizes: currently 4096, max supported 4096
--11984-- Valgrind library directory: /usr/local/lib/valgrind
--11984-- Reading syms from /lib/ld-2.9.so
--11984-- Reading syms from /root/cs5513/cache_sim
--11984-- Reading syms from /usr/local/lib/valgrind/memcheck-x86-linux
--11984--    object doesn't have a dynamic symbol table
--11984-- Scheduler: using generic scheduler lock implementation.
--11984-- Reading suppressions file: /usr/local/lib/valgrind/default.supp
==11984== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-11984-by-root-on-ariel.darkterminal.net
==11984== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-11984-by-root-on-ariel.darkterminal.net
==11984== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-11984-by-root-on-ariel.darkterminal.net
==11984== 
==11984== TO CONTROL THIS PROCESS USING vgdb (which you probably
==11984== don't want to do, unless you know exactly what you're doing,
==11984== or are doing some strange experiment):
==11984==   /usr/local/lib/valgrind/../../bin/vgdb --pid=11984 ...command...
==11984== 
==11984== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==11984==   /path/to/gdb ./cache_sim
==11984== and then give GDB the following command
==11984==   target remote | /usr/local/lib/valgrind/../../bin/vgdb --pid=11984
==11984== --pid is optional if only one valgrind process is running
==11984== 
--11984-- REDIR: 0x4018d50 (strlen) redirected to 0x3803fe64 (vgPlain_x86_linux_REDIR_FOR_strlen)
--11984-- REDIR: 0x4018b60 (index) redirected to 0x3803fe3f (vgPlain_x86_linux_REDIR_FOR_index)
--11984-- Reading syms from /usr/local/lib/valgrind/vgpreload_core-x86-linux.so
--11984-- Reading syms from /usr/local/lib/valgrind/vgpreload_memcheck-x86-linux.so
--11984-- Reading syms from /lib/libm-2.9.so
--11984-- Reading syms from /lib/libc-2.9.so
--11984-- REDIR: 0x40ed650 (rindex) redirected to 0x4027c90 (rindex)
--11984-- REDIR: 0x40f1d60 (strchrnul) redirected to 0x402a5b0 (strchrnul)
index = 8
tag = 19
offset = 5
--11984-- REDIR: 0x40e94b0 (malloc) redirected to 0x4026df0 (malloc)
num_of_sets = 256
assoc = 4
both = 1024
cache_array = BED06840
replace_array = BED0683C
--11984-- REDIR: 0x40ee2e0 (strstr) redirected to 0x402a840 (strstr)
--11984-- REDIR: 0x40eea80 (memchr) redirected to 0x4028860 (memchr)
--11984-- REDIR: 0x40ef210 (memcpy) redirected to 0x4028ec0 (memcpy)
--11984-- REDIR: 0x40eecf0 (memset) redirected to 0x4029fe0 (memset)
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8048FC1: main (cache_sim.c:284)
==11984== 
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8049264: main (cache_sim.c:366)
==11984== 
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8048F95: main (cache_sim.c:280)
==11984== 
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x804923A: main (cache_sim.c:362)
==11984== 
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8049052: main (cache_sim.c:299)
==11984== 
==11984== Invalid read of size 4
==11984==    at 0x804925F: main (cache_sim.c:366)
==11984==  Address 0x41d8028 is 0 bytes after a block of size 4,096 alloc'd
==11984==    at 0x4026E72: malloc (vg_replace_malloc.c:270)
==11984==    by 0x804899A: main (cache_sim.c:96)
==11984== 
==11984== Invalid write of size 4
==11984==    at 0x8049476: main (cache_sim.c:426)
==11984==  Address 0x41d8030 is 8 bytes after a block of size 4,096 alloc'd
==11984==    at 0x4026E72: malloc (vg_replace_malloc.c:270)
==11984==    by 0x804899A: main (cache_sim.c:96)
==11984== 
--11984-- REDIR: 0x40ed1e0 (strlen) redirected to 0x4028160 (strlen)
--11984-- REDIR: 0x40eed50 (mempcpy) redirected to 0x402a620 (mempcpy)
--11984-- REDIR: 0x40e7050 (free) redirected to 0x4026830 (free)
==11984== 
==11984== HEAP SUMMARY:
==11984==     in use at exit: 5,824 bytes in 4 blocks
==11984==   total heap usage: 4 allocs, 0 frees, 5,824 bytes allocated
==11984== 
==11984== Searching for pointers to 4 not-freed blocks
==11984== Checked 60,944 bytes
==11984== 
==11984== LEAK SUMMARY:
==11984==    definitely lost: 0 bytes in 0 blocks
==11984==    indirectly lost: 0 bytes in 0 blocks
==11984==      possibly lost: 0 bytes in 0 blocks
==11984==    still reachable: 5,824 bytes in 4 blocks
==11984==         suppressed: 0 bytes in 0 blocks
==11984== Rerun with --leak-check=full to see details of leaked memory
==11984== 
==11984== Use --track-origins=yes to see where uninitialised values come from
==11984== ERROR SUMMARY: 72984 errors from 7 contexts (suppressed: 13 from 6)
==11984== 
==11984== 4 errors in context 1 of 7:
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x804923A: main (cache_sim.c:362)
==11984== 
==11984== 
==11984== 17 errors in context 2 of 7:
==11984== Invalid write of size 4
==11984==    at 0x8049476: main (cache_sim.c:426)
==11984==  Address 0x41d8030 is 8 bytes after a block of size 4,096 alloc'd
==11984==    at 0x4026E72: malloc (vg_replace_malloc.c:270)
==11984==    by 0x804899A: main (cache_sim.c:96)
==11984== 
==11984== 
==11984== 28 errors in context 3 of 7:
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8049052: main (cache_sim.c:299)
==11984== 
==11984== 
==11984== 100 errors in context 4 of 7:
==11984== Invalid read of size 4
==11984==    at 0x804925F: main (cache_sim.c:366)
==11984==  Address 0x41d8028 is 0 bytes after a block of size 4,096 alloc'd
==11984==    at 0x4026E72: malloc (vg_replace_malloc.c:270)
==11984==    by 0x804899A: main (cache_sim.c:96)
==11984== 
==11984== 
==11984== 312 errors in context 5 of 7:
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8048F95: main (cache_sim.c:280)
==11984== 
==11984== 
==11984== 1225 errors in context 6 of 7:
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8049264: main (cache_sim.c:366)
==11984== 
==11984== 
==11984== 71298 errors in context 7 of 7:
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8048FC1: main (cache_sim.c:284)
==11984== 
--11984-- 
--11984-- used_suppression:     13 U1004-ARM-_dl_relocate_object
==11984== 
==11984== ERROR SUMMARY: 72984 errors from 7 contexts (suppressed: 13 from 6)
-Tristan

Last edited by trist007; 11-04-2012 at 09:15 PM.
 
Old 11-04-2012, 09:33 PM   #3
trist007
Senior Member
 
Registered: May 2008
Distribution: Slackware
Posts: 1,052

Original Poster
Rep: Reputation: 70
If I run it normally it segfaults. It segfaults as a result of replace_array[0] becoming that large value. However, if I use valgrind, the output comes out successfully with no segfault.

-Tristan

Last edited by trist007; 11-04-2012 at 09:40 PM.
 
Old 11-04-2012, 09:50 PM   #4
trist007
Senior Member
 
Registered: May 2008
Distribution: Slackware
Posts: 1,052

Original Poster
Rep: Reputation: 70
I had called malloc to two int *arrays. I malloc'd them one after the other, cache_array and replace_array. This time, I moved one of the malloc's further down the code and now it works fine. How is it that calling malloc on both of the pointers one after the other would cause conflicts like an invalid pointer when calling free()?

-Tristan

Last edited by trist007; 11-04-2012 at 10:24 PM.
 
Old 11-05-2012, 04:48 AM   #5
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by trist007 View Post
Here's the output of valgrind, in case it'll shed some light.
Code:
root@ariel:~625> valgrind -v ./cache_sim 32 32 4 sample5.in sick
...
==11984== Conditional jump or move depends on uninitialised value(s)
==11984==    at 0x8048FC1: main (cache_sim.c:284)
...
Best to start at the first error, anything that happens after that could be a result of it. What is the code doing around line 284?
 
Old 11-05-2012, 07:49 AM   #6
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941
Do you know that the memory for the array has been initialized to any known value? Do you know that the computed array-index actually falls within the boundaries of the array?
 
Old 11-05-2012, 08:05 AM   #7
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
You gave evidence multiple different ways of an error you almost seem to understand. Why didn't you simply look at the relevant variables and understand the error.

If you care, the relevant part of the valgrind output is:

Quote:
Code:
==11984== Invalid write of size 4
==11984==    at 0x8049476: main (cache_sim.c:426)
==11984==  Address 0x41d8030 is 8 bytes after a block of size 4,096 alloc'd
But that doesn't mean the rest of what valgrind found is safe to ignore. Also you didn't really need valgrind, since the rest of what you posted also identifies the fault.

Quote:
Originally Posted by trist007 View Post
This is in C
Code:
else if (cache_index == 255) {
  n = replace_array[cache_index];
  cache_array[((cache_index * assoc) + assoc) + n] = cache_tag;
}
...
Is this some sort of overflow?
Of course.

The value of ((cache_index * assoc) + assoc) + n is obviously greater than the number of elements in cache_array. So when you hit that hardware breakpoint, you should have looked at the values of cache_index, assoc and n to determine which of them is larger than you expected, then find out why.

Quote:
Originally Posted by trist007 View Post
If I run it normally it segfaults. It segfaults as a result of replace_array[0] becoming that large value. However, if I use valgrind, the output comes out successfully with no segfault.
When you run it normally, replace_array is allocated just 8 bytes later in memory than cache_array. Your code exceeds the size of cache_array (by at least 12 bytes) clobbering those 8 bytes and clobbering at least four more bytes (the first four bytes of replace_array.

When you run with Valgrind, Valgrind inserts extra space between the allocation of cache_array and the allocation of replace_array, so when your program still clobbers beyond the end of cache_array that doesn't affect replace_array.

Quote:
Originally Posted by trist007 View Post
I had called malloc to two int *arrays. I malloc'd them one after the other, cache_array and replace_array. This time, I moved one of the malloc's further down the code and now it works fine. How is it that calling malloc on both of the pointers one after the other would cause conflicts like an invalid pointer when calling free()?
Two sequential calls to malloc, in a program that hasn't previously released fragmented allocated memory, typically gives you contiguous blocks. The eight bytes immediately after the first block contain control information that will be needed when freeing the second block. When your program clobbers those eight bytes that has no immediate symptom, but later causes the free operation to go wrong.

If the second block is allocated later (after some other unrelated allocation) then that other free operation is the one that will go wrong and maybe you never freed that other chunk.

If you aren't skilled at use of the debugger, you could patch that section of the program to give you info about the bug:

Code:
else if (cache_index == 255) {
  n = replace_array[cache_index];
  if ( 1024 <= ((cache_index * assoc) + assoc) + n ) {
    printf("Bug detected:  cache_index=%d, assoc=%d, n=%d\n"
      cache_index, assoc, n);
    exit(-1); }
  cache_array[((cache_index * assoc) + assoc) + n] = cache_tag;
}
I inferred the 1024 from your valgrind output. Hopefully there is some symbolic version of that used when you malloc'ed cache_array. Using that symbolic version is cleaner than the 1024 I put in the above code.

Also, why do you add assoc in that index expression that goes wrong? I understand multiplying by assoc and adding n, but I don't understand the extra add of assoc. That might be the entire cause of the bug.

Last edited by johnsfine; 11-05-2012 at 08:26 AM.
 
Old 11-05-2012, 09:20 AM   #8
trist007
Senior Member
 
Registered: May 2008
Distribution: Slackware
Posts: 1,052

Original Poster
Rep: Reputation: 70
Fantastic. Thank you for all the good input. I like that code snippet about checking the bounds johnsfine thank you, it helped me fine the issue. I added assoc again to access the next cache block for my given data structure. It makes sense now, an overflow, which is what caused replace_array[0] to have the value of cache_tag. Thank you.

Great stuff.

-Tristan
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Does calling an element of an array calls the whole array unkn(0)wn Programming 3 07-06-2012 07:50 PM
[perl] copying an array element into another array s0l1dsnak3123 Programming 2 05-17-2008 01:47 AM
invalid types ‘int[int]’ for array subscript medha Programming 16 08-25-2006 08:30 AM
invalid types int[int] for array subscript scuzzman Programming 2 11-16-2004 09:34 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:34 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration