cross-posted from: https://lemmy.ml/post/21033409

In the book authored by K.N.King, there’s this example:

viewmemory.c
/* Allows the user to view regions of computer memory */

#include <stdio.h>
#include <ctype.h>

typedef unsigned char BYTE;

int main(void)
{
	unsigned int addr;
	int i, n;
	BYTE *ptr;
	
	printf("Address of main function: %x\n", (unsigned int) main);
	printf("Address of addr variable: %x\n", (unsigned int) &addr);
	printf("\nEnter a (hex) address: ");
	scanf("%x", &addr);
	printf("Enter number of bytes to view: ");
	scanf("%d", &n);
	
	printf("\n");
	printf(" Address               Bytes             Characters\n");
	printf(" ------- ------------------------------- ----------\n");
	
	ptr = (BYTE *) addr;
	for (; n > 0; n -= 10) {
		printf("%8X  ", (unsigned int) ptr);
		for (i = 0; i < 10 && i < n; i++)
			printf("%.2X ", *(ptr + i));
		for (; i < 10; i++)
			printf("   ");
		printf(" ");
		for (i = 0; i < 10 && i < n; i++) {
			BYTE ch = *(ptr + i);
			if (!isprint(ch))
				ch = '.';
			printf("%c", ch);
		}
		printf("\n");
		ptr += 10;
	}
	
	return 0;
}

For some reason, when I try to enter addr variable address as the parameter, it has a segmentation fault error. However, in the book’s example and the screenshot from this site in Hangul, there’s no such error?

When I try using gdb to check the issue, here’s what I get:

gdb
$ gdb ./a.out  --silent
Reading symbols from ./a.out...
(gdb) run
Starting program: /home/<username>/Desktop/c-programming-a-modern-approach/low-level-programming/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/gnu/store/zvlp3n8iwa1svxmwv4q22pv1pb1c9pjq-glibc-2.39/lib/libthread_db.so.1".
Address of main function: 401166
Address of addr variable: ffffd678

Enter a (hex) address: ffffd678
Enter number of bytes to view: 64

 Address               Bytes             Characters
 ------- ------------------------------- ----------

Program received signal SIGSEGV, Segmentation fault.
0x000000000040123a in main () at viewmemory.c:31
warning: Source file is more recent than executable.
31	        printf ("%.2X ", *(ptr + i));
(gdb)

What is going on? By the way, I am using Guix, if that matters in any way. Here’s the output for ldd:

ldd
$ ldd ./a.out 
	linux-vdso.so.1 (0x00007ffecdda9000)
	libgcc_s.so.1 => /gnu/store/w0i4fd8ivrpwz91a0wjwz5l0b2ralj16-gcc-11.4.0-lib/lib/libgcc_s.so.1 (0x00007fcd2627a000)
	libc.so.6 => /gnu/store/zvlp3n8iwa1svxmwv4q22pv1pb1c9pjq-glibc-2.39/lib/libc.so.6 (0x00007fcd2609c000)
  • LalSalaamComradeOP
    link
    fedilink
    English
    arrow-up
    3
    ·
    edit-2
    5 hours ago

    This worked for me - I think %p fixed the issue of incorrect representation, as well as input. I also tried unsigned long int, which works in place of uintptr_t, but I’m assuming that it isn’t portable.

    Resolved code snippet
    /* Allows the user to view regions of computer memory */
    
    #include <ctype.h>
    #include <stdint.h>
    #include <stdio.h>
    
    typedef unsigned char BYTE;
    
    int
    main (void)
    {
      uintptr_t addr;
      int i, n;
      BYTE *ptr;
    
      printf ("Address of main function: %p\n", (void *) &main);
      printf ("Address of addr variable: %p\n", (void *) &addr);
      printf ("\nEnter a (hex) address: ");
      scanf ("%p", &addr);
      printf ("Enter number of bytes to view: ");
      scanf ("%d", &n);
    
      printf ("\n");
      printf (" Address               Bytes             Characters\n");
      printf (" ------- ------------------------------- ----------\n");
    
      ptr = (BYTE *) addr;
      for (; n > 0; n -= 10)
        {
          printf ("%8X  ", (uintptr_t) ptr);
          for (i = 0; i < 10 && i < n; i++)
            printf ("%.2X ", *(ptr + i));
          for (; i < 10; i++)
            printf ("   ");
          printf (" ");
          for (i = 0; i < 10 && i < n; i++)
            {
              BYTE ch = *(ptr + i);
              if (!isprint (ch))
                ch = '.';
              printf ("%c", ch);
            }
          printf ("\n");
          ptr += 10;
        }
    
      return 0;
    }