Tuesday, September 28, 2010

char*ptr Vs char ptr[]

Why as follows program works in Sunstudio C compiler but segmentation faults in gcc:

int
main()
{
char *ptr = "hello";
ptr[2] = 'v';
printf("ptr = %s\n", ptr);
return 0;
}

# gcc charPtr.c
# ./a.out
Segmentation Fault (core dumped)
# cc charPtr.c
# ./a.out
ptr = hevlo

You can get a segmentation fault with Sun Studio as well if you use
-xstrconst. This option makes the string nonwritable.

You can't write into string constants as per the ANSI C standard, but the
Sun compiler will let you do it unless you specify -xstrconst.

ptr' itself is allocated in the stack. However, the literal
string "bhushan" is stored in .rodata (static memory area).

You actually have two objects there -- a pointer, which is itself mutable, and a constant string, which might or might not be, depending on compiler option.

Here pointer ptr is pointing to the "bhushan" that is stored in read only memory therefore you are trying to change the read only memory conents. This will obviously gives you Core dump.

To work this do as follows:
1. Change your declaration as follows:
char * ptr= "bhushan" to char ptr[]= "bhushan"
OR
2. Allocate the memory for the ptr first using malloc.

In the above two points this will works using both cc and gcc compiler. In these cases "bhushan" will stored in Readonly memory and and "bhushan" will copied to the stack memory allocated for ptr when main is called.
Therfor you can changes this string using ptr on stack.

How can create own section in memory

//mysection.c: this program tells how we can create own section and also put our varible inside this section
#include

int my_func (int, int) __attribute__ ((section ("my_code_section")));
int global_var __attribute__ ((section ("my_data_section")));
int global_init __attribute__ ((section ("my_data_section"))) = 2;

int my_func (int i, int j)
{
return i*j;
}

int
main (void)
{
int local_var = 10;
global_init = 5;

printf ("local_var: %d global_var: %d global_init: %d\n",
local_var, global_var, global_init);
printf ("%d * %d = %d\n", local_var, global_var,
my_func (local_var, global_var));

return 0;
}
$gcc mysection.c
$./a.out
local_var: 10 global_var: 0 global_init: 5
10 * 0 = 0

How to call a function before main and after main

1. Using GCC compiler on Linux/Solaris

/*main.c :this program tells how we can call a function before main() call and after main() call*/

#include

void my_ctor (void) __attribute__ ((constructor));
void my_dtor (void) __attribute__ ((destructor));

void
my_ctor (void)
{
printf ("hello before main()\n");
}

void
my_dtor (void)
{
printf ("bye after main()\n");
}

int
main (void)
{
printf ("hello\n");
return 0;
}

$gcc main.c
$./a.out
hello before main()
hello
bye after main()


2. Using CC compiler on Solaris[Using Pragma]

Using pragma
============


#pragma init (foo)

void foo()
{
printf("\nInside foo");
}

#pragma fini (bar)

void bar()
{
printf("\nInside bar");
}

int
main()
{
printf("\nInside main");
return 0;
}

$cc main.c
$./a.out
Inside foo
Inside main
Inside bar

How we can call a function after exiting from main() Using ATEXIT()

//atexit.c: this program shows how we can call a function after exiting from main() function
#include
#include

void my_func1(void);
void my_func2(void);

int main(int argc, char** argv)
{
atexit(my_func1);
atexit(my_func2);
printf("Inside main\n");
exit(0);

}

void
my_func1(void)
{
printf("\ninside my_func1 ");
}

void
my_func2(void)
{
printf("\ninside my_func2 ");
}


$gcc atexit.c
$./a.out

Inside main
inside my_func2
inside my_func1

Tuesday, September 14, 2010

Is malloc(0) call is Valid or invalid?

Yes malloc(0) is valid but this is implementation, system dependent(Memory manager/OS/GLIBC).

Take an example for 32 bit machine(Linux/Solaris):
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
printf("Got a null pointer\n");
else
printf("Got a valid pointer\n");

I have tried the above code snippet in linux/solaris machine.Its output is:
Got a valid pointer

Even a request for zero bytes (i.e., malloc(0)) returns a pointer to something of the minimum allocatable size.

The above is implementation dependent.Therfore malloc(0) call is Valid.

few things to know for details see below *Vital statistics column:
Minimum allocated size:
4-byte ptrs: 16 bytes (including 4/8 bytes overhead)


Alignment: 2 * sizeof(size_t) (default)
(i.e., 8 byte alignment with 4byte size_t). This suffices for nearly all current machines and C compilers. However, you can define MALLOC_ALIGNMENT to be wider than this if necessary.

Malloc padded to a multiple of 8 for 8 byte alignment.Minimum overhead: 8 byte[Each malloced chunk has a hidden word of overhead holding size and status information.]

take an example and run this on linux/solaris 32 bit machine:
int j, *buf;

for (j = 0; j < 10; j++) {
buf = (int *) malloc(10);
printf("malloc(10) returned 0x%x\n", buf);
}

malloc(10) returned 0x20968
malloc(10) returned 0x20980
malloc(10) returned 0x20998
malloc(10) returned 0x209b0
malloc(10) returned 0x209c8
malloc(10) returned 0x209e0
malloc(10) returned 0x209f8
malloc(10) returned 0x20a10
malloc(10) returned 0x20a28
malloc(10) returned 0x20a40

Here malloc() allocates some extra bytes(overhead bytes that contains allocated memory size etc) each time it is called so that it can do bookkeeping. These extra bytes help out when free() is called.
These extra bytes are often allocated before the returned memory.
The difference for every 10 byte memory allocation is 24 bytes[16 byte for user(10 + 6 byte for making 8 byte alignment) + 8 byte overhead].

Overhead contains as following info and that is used during free the memory:

  • The actual size of the allocated memory block.
  • An indicator as to whether the block is in use, or has been freed.

The above information is based on GLIBC.For more information refer Glibc source code.

Please note that the smallest allowed allocation is 32 bytes on a 64-bit system. 

 ======================================================================
Below taken from GLIBC code:
* Vital statistics:

  Supported pointer representation:       4 or 8 bytes
  Supported size_t  representation:       4 or 8 bytes
       Note that size_t is allowed to be 4 bytes even if pointers are 8.
       You can adjust this by defining INTERNAL_SIZE_T

  Alignment:                              2 * sizeof(size_t) (default)
       (i.e., 8 byte alignment with 4byte size_t). This suffices for
       nearly all current machines and C compilers. However, you can
       define MALLOC_ALIGNMENT to be wider than this if necessary.

  Minimum overhead per allocated chunk:   4 or 8 bytes
       Each malloced chunk has a hidden word of overhead holding size
       and status information.

  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
              8-byte ptrs:  24/32 bytes (including, 4/8 overhead)

       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
       needed; 4 (8) for a trailing size field and 8 (16) bytes for
       free list pointers. Thus, the minimum allocatable size is
       16/24/32 bytes.

       Even a request for zero bytes (i.e., malloc(0)) returns a
       pointer to something of the minimum allocatable size.

       The maximum overhead wastage (i.e., number of extra bytes
       allocated than were requested in malloc) is less than or equal
       to the minimum size, except for requests >= mmap_threshold that
       are serviced via mmap(), where the worst case wastage is 2 *
       sizeof(size_t) bytes plus the remainder from a system page (the
       minimal mmap unit); typically 4096 or 8192 bytes.

  Maximum allocated size:  4-byte size_t: 2^32 minus about two pages
               8-byte size_t: 2^64 minus about two pages