Common memory-related errors in C Programs

Source: Internet
Author: User

[Transferred from: deep understanding of computer systems, Randal E. Bryant & David O 'allaron]


10.11 common memory-related errors in C Programs

For C programmers, managing and using virtual memory can be a difficult and error-prone task. Memory-related errors are the most frightening errors because they are often displayed after a distance from the error source in terms of time and space. Write the wrong data to the wrong location. Your program may run for several hours before the final failure, and the location of the program to be aborted is far away from the wrong location.


10.11.1 indirect reference of bad pointer


There are large holes in the virtual address space of the process, and no meaningful data is mapped. If we try to indirectly reference a pointer pointing to these holes, the operating system will terminate our program with a segment exception. In addition, some areas of the virtual memory are read-only. Attempting to write these areas will result in terminating the program with protection exceptions.

A common example of indirect reference of bad pointers is the classic scanf error. Suppose we want to use scanf to read an integer from stdin to a variable. The correct way to do this is to pass a format string and variable address to scanf:

Scanf ("% d", & Val );

However, for beginners of C programmers (also for experienced programmers !), It is easy to pass Val content, rather than its address:

Scanf ("% d", Val );

In this case, scanf interprets the Val content as an address and tries to write a word to this location. In the best case, the program immediately terminates with an exception. In the worst case, the Val content corresponds to a valid read/write area of the virtual memory, so we overwrite the memory, this usually results in disastrous and confusing consequences after quite a while.


10.11.2 read uninitialized memory

Although the location of the. BSS memory (such as the uninitialized global C variable) is initialized to zero by the loader, this is not the case for heap memory. A common error is that the heap memory is initialized to zero:

int *matvec(int **A, int *x, int n){    int i, j;    int *y = (int *) malloc(n *sizeof(int));    for (i = 0; i < n; i++)    {        for (j = 0; j < n; j++)        {            y[i] += A[i][j] * x[j];        }    }     return y;}

In this example, the programmer incorrectly assumes that vector y is initialized to zero. The correct implementation method is to set Y [I] to zero before the second for, or use calloc.


10.11.3 stack buffer overflow allowed


If a program writes data to the target buffer zone of the stack without checking the size of the input string, the program will encounter a buffer overflow error (buffer overflow bug ). For example, the following function has a buffer error because the gets function copies a string of any length to the buffer. To correct this error, we must use the fgets function, which limits the size of the input string.

void bufoverflow(){char buf[64];gets(buf); /* here is the stack buffer overflow bug */return;}  
10.11.4 assume that the pointer and the object they direct to are of the same size.


A common error is that the pointer to an object is the same size as the object to which it points:

/* Createan n * m array */int **makeArray1(int n, int m){    int i;    int **A = (int **) malloc(n * sizeof(int));    for (i = 0; i < n; i++)        A[i] = (int *)malloc(m * sizeof(int));     return A;}

The purpose here is to create an array composed of N pointers, each pointing to an array containing M Int. However, because the programmer writes sizeof (int *) in the 5th line, the Code actually creates an int array. This code runs well only on machines with the same int and INT pointer sizes.

However, if we run this code on a machine such as alpha, where the pointer is greater than int, the loops of rows 7th and 8th will be written beyond the end of array. Because one of these words is likely to mark the foot with the boundary of the allocated block, we may not find this error until after this program is executed for a long time, we release the block, at this point, the merging code in the alignment fails dramatically without any obvious reason. This is a sinister example of "action at distance", which is a typical scenario of memory-related programming errors.


10.11.5 misplacement Error

 

The off-by-one error is another common cause of overwrite errors:

/* Createan n * m array */int**makeArray2(int n, int m){    int i;    int **A = (int **) malloc(n *sizeof(int *));    for (i = 0; i <= n; i++)        A[i] = (int *) malloc(m * sizeof(int));    return A;}


This is another version of the program in the previous section. Here we create a pointer array of n elements in row 5th, but then we attempt to initialize n + 1 elements of the array in row 7th and row 8th, in this process, a memory after array a is overwritten.

10.11.6 references the pointer instead of the object it points.

 

If we do not pay much attention to the priority and combination of the C operator, we will mistakenly operate the pointer rather than the object to which the operation pointer is expected to point. For example, consider the following function to delete the first item in a binary heap with * size items, and then re-build the heap for the remaining * size-1 items.

int*binheapDelete(int **binheap, int *size){    int *packet = binheap[0];    binheap[0] = binheap[*size - 1];    *size--; /*this should be (*size)-- */    heapipfy(binheap, *size, 0);    return (packet);}

In row 6th, the objective is to reduce the integer value (that is, (* size) --) pointed to by the size pointer )--). However, because the value of one dollar is combined with the * operator priority from the right to the left, the Code in line 6th actually reduces the value of the pointer rather than the integer it points. If we are lucky, the program will fail immediately, but it is more likely that when the program produces an incorrect result after the execution process, we can only crack our head there. The principle here is that if you have questions about priority and associativity, use brackets. For example, in row 6th, we can clearly express our purpose and use the expression (* size )--.


10.11.7 misunderstanding pointer operation

 

Another common mistake is that arithmetic operations that forget pointers are performed in units of the size of the objects they point to, and this size unit is not necessarily a byte. For example, the purpose of the following function is to scan an int array and return a pointer pointing to the first appearance of Val:

int*search(int *p, int val){    while (*p && *p != val)        p += sizeof(int); /* should be p++ */    return p;}


However, because each cycle adds 4 (the number of bytes of an integer) to the pointer in the first row, the function does not correctly scan the 4th integers in the array.

10.11.8 reference a variable that does not exist

C programmers without much experience do not understand the stack rules, and sometimes reference local variables that are no longer valid, as shown in the following:

int*stackref(){    int val;    return &val;} 

This function returns a pointer (for example, p) pointing to a local variable in the stack, and then its stack frame pops up. Although P still points to a valid memory address, it no longer points to a valid variable. When other functions are called in the program in the future, the memory will reuse their stack frames. Later, if a program assigns a value to * P, it may be modifying an entry in the stack frame of another function, resulting in potentially disastrous and confusing consequences.


10.11.9 reference data in the idle heap Block

A similar error is that the data in the released heap block is referenced. For example, consider the following example. In this example, an integer array X is allocated in row 6th, blocks are released in row 10th, and then referenced in row 14th.

int *heapref(int n, int m){    int i;    int *x, *y;    x = (int *) malloc(n *sizeof(int));    /* ... */ /* other calls to malloc and free go here */    free(x);    y = (int *) malloc m * sizeof(int));    for (i = 0; i < m, i++)        y[i] = x[i]++; /*oops! x[i] is a word in a free block */    return y;}


Depending on the malloc and free call modes that occur in lines 6th and 10th, when the program references X [I] In line 14th, array X may be part of another allocated block, so its content is overwritten. When many other memory-related errors are the same, they will only appear after the execution of the program and when we notice that the value in Y is broken.


10.11.10 Memory leakage

 

Memory leakage is a slow, hidden killer. This problem occurs when a programmer accidentally forgets to release allocated blocks and creates garbage in the heap. For example, the following function allocates a heap block X and returns the result without releasing it.


voidleak(int n){    int *x = (int *)malloc(n *sizeof(int));    return; /* x is garbage at this point */}

If leak is often called, gradually the heap will be full of garbage. In the worst case, it will occupy the entire virtual address space. For programs such as daemon and servers, memory leaks are extremely serious and will not be terminated as defined.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.