tags:

views:

123

answers:

2

Hi all,

I have the following code:

#include <stdlib.h>
#include <stdio.h>

#define SIZE 100

int* arr;

main()
{
    int i;

    arr = (int*)malloc(SIZE*sizeof(int));

    if (arr == NULL) {
        printf("Could not allocate SIZE(=%d)", SIZE);
    }

    for (i=0; i<SIZE; i++) {
        arr[i] = 0;
    }

    free(arr);
}

I wan't to watch for arr[10] and see when that array element is being modified.

How can I do this? gdb says the following:

$ gcc -g main.c
$ gdb a.out
...
(gdb) watch arr[10]
Cannot access memory at address 0x28

Is there a way to tell gdb to watch an invalid memory and stop only when it becomes valid?

PS: I have gdb versions 6.0, 6.3, 6.4, 6.6, 6.8, 7.0 and 7.1

Thanks

A: 

Set the watch after the memory has been allocated with malloc.

(gdb) b main
Breakpoint 1 at 0x401321: file w.c, line 9.
(gdb) run
Starting program: D:\Users\NeilB/a.exe
[New thread 432.0x53c]

Breakpoint 1, main () at w.c:9
9       {
(gdb)
(gdb) n
12          arr = (int*)malloc(SIZE*sizeof(int));
(gdb) n
14          if (arr == NULL) {
(gdb) watch arr[10]
Hardware watchpoint 2: arr[10]
anon
That would work, the problem is that that solution doesn't work for me. The example is part of a bigger program, which i'm trying to debug, where the array is being reallocated multiple times. Whenever the debugger stops for something, it introduces enough overhead to make the bug go away. So I can't intervene in the middle of the execution.
Gastón
@Gaston well, you cannot set a watch on memory your process does not yet own. and if the array ifs re-allocated, any watch on it will become invalidated. I take it this is a multi-threaded app?
anon
@Neil that's right, it's a multi-threaded app. Thank's for the info. Maybe I could set a breakpoint right after memory is reallocated, and then with the gdb commands instruction, set the watchpoint if the process owns the memory (if the array is bigger than the index I wan't to watch). Is it possible? To set a watchpoint if a condition is met? (note that this is different from the gdb conditional instruction).
Gastón
@gaston To be frank, I've always found debuggers to be useless for debugging MT apps, because of the timing issues. When doing MT debugging I depend on thinking hard, code inspection by several people, and ye olde printf-to-a-log as a last resort.
anon
@Neil Hey! It worked with gdb-7.0 and onwards. I answered my question with an example. Hope this helps for debugging my threaded application.
Gastón
A: 

Hi,

For some reason, I was using gdb-6.3 (it was in my PATH and I didn't notice it). But, when I tried with gdb-7.1 it worked!

Since gdb 7.0 you can watch memory that isn't yours at the moment.

With the following source code:

#include <stdlib.h>
#include <stdio.h>

#define SIZE 100

int* arr;

main()
{
    int i;

    arr = (int*)malloc(SIZE*sizeof(int));

    if (arr == NULL) {
        printf("Could not allocate SIZE(=%d)", SIZE);
    }

    for (i=0; i<SIZE; i++) {
        arr[i] = i; /* So it changes from malloc */
    }

    free(arr);
}

You can compile with:

$ gcc -g -o debug main.c

And then debug with:

$ gdb debug
GNU gdb (GDB) 7.1
...
(gdb) watch arr[10]
Watchpoint 1: arr[10]
(gdb) run
Starting program: /remote/cats/gastonj/sandbox/debug/debug
Hardware watchpoint 1: arr[10]

Old value = <unreadable>
New value = 0
main () at main.c:14
14          if (arr == NULL) {
(gdb) cont
Continuing.
Hardware watchpoint 1: arr[10]

Old value = 0
New value = 10
main () at main.c:18
18          for (i=0; i<SIZE; i++) {
(gdb) cont
Continuing.

Program exited with code 01.
(gdb)

Hope it helps for somebody else.

NOTE: I tried adding this as a comment in the post by Neil, but as it wasn't formatted, I preferred writing an answer to my question.

Gastón