Common memory operation errors in C programs

Source: Internet
Author: User

Managing and using virtual storage can be a difficult, error-prone task for a C + + programmer. Memory-related errors are those that are scary, because they are often displayed in time and space after a distance from the source of the error. By writing the wrong data to the wrong location, your program may have been running for several hours before the final failure, and the location of the program abort is far from the wrong location. The best way to avoid this nightmare is to prevent it from happening.

Fortunately, "in-depth understanding of computer systems," there is a paragraph: C program common memory operations related to the 10 typical programming errors , very classic, so copied here so that you can review at any time, review.

To become a good habit, although not to, yearn.

1. Indirect reference Invalid pointer


Some address ranges of the process virtual address space may not be mapped to any meaningful data, and if we attempt to indirectly reference a pointer to those addresses, the operating system terminates the process with segment fault. Also, some areas of the virtual storage are read-only (such as. text or. rodata), and attempting to write these areas will abort the current process with a protection exception.
If an int variable is read from stdin, scanf ("%d", &val) is the correct usage, and if it is mistakenly written as scanf ("%d", Val), the Val value is interpreted as an address and an attempt is made to write data to that address. In the best case, the process immediately aborts abnormally. In the worst case, Val's value corresponds exactly to a valid memory area of the virtual memory that has read/write permission, and the memory unit is rewritten, which usually has disastrous and confusing consequences over a long period of time. When we are learning pointers in C + +, pointer uninitialized errors are also part of this type of error.



2. Read uninitialized storage (Reading uninitialized memory)


The C-language malloc is not responsible for initializing the requested memory area (the uninitialized global variables in C + + will be initialized to 0), so a common mistake is to assume that the heap memory is initialized to 0, for example:

This program computes a n*n matrix (**a) multiplied by a n*1 (*x) matrix and returns the computed result (*y).

//Return y = Axint*matvec (int**a,int*x,intN) {    intI, 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]; returny;}


In the above code, it is incorrectly assumed that Y is initialized to 0. The correct implementation is to explicitly set Y[i to 0 or use Calloc to allocate memory.


3. Stack buffers overflow (allowing stack buffer overflows)

This is the familiar buffer overflow error (buffer overflow bug)

void Bufoverflow () {    char buf[];       // Here is the stack buffer overflow bug     gets (BUF);      return ; }

If you enter more than 64 characters, the above code will cause the stack buffer to overflow. You can use the Fgets function instead of the Get function, and the Fget function has a second argument to limit the size of the input string.



4. Mistakenly assume that the pointer and the object they point to are the same size. (assuming that pointers and the Objects they point to is the same Size)


For example: To apply for a two-dimensional n*m int array space.

1 //Create an NXM array2 int**makearray1 (intNintm)3 {4     inti;5     int**a = (int**)malloc(n *sizeof(int));//Wrang6     // Right7     //int **a = (int * *) malloc (n * sizeof (int *));8 9      for(i =0; I < n; i++)TenA[i] = (int*)malloc(M *sizeof(int));  One     returnA;  A}


The purpose of the code above is to create an array of n pointers, each pointing to an array containing M int, but the fifth line mistakenly writes sizeof (int *) as sizeof (int). This code works well on machines with the same size as int and int *. If you run this code on a machine like Core i7, because the pointer variable has a size greater than sizeof (int), the For loop write out of the code is thrown out of bounds. Because one of these words is likely to be the boundary marker foot of the allocated block, we may not find this error immediately until the process has freed the memory block for a long time, and the merge code in the allocator will fail dramatically without any apparent reason. This is a covert example of "working in the Distance" (action at distance), which is a typical case of memory-related programming errors, such as "working in the distance".


5. Error causing dislocation (Making Off-by-one Errors)


Misplaced (off-by-one) errors are another common source of coverage errors:

1 //Create an NXM array2 int**makearray2 (intNintm)3 {4     inti;5     int**a = (int**)malloc(n *sizeof(int*)); 6 7      for(i =0; I <= N; i++)8A[i] = (int*)malloc(M *sizeof(int)); 9     returnA;Ten}


Obviously, the For loop times out of expectation, resulting in a write out of bounds. Fortunately, the process crashes immediately; Unfortunately, it takes a long time to throw up all sorts of weird problems.



6. Reference pointer, not the object it points to (referencing a Pointer Instead of the The object it Points to)


If you do not pay attention to the precedence and associativity of the C operator, the pointer is manipulated incorrectly, not the object that the pointer points to.
For example, the following function is intended to delete the first item in a two-fork heap with *size items, and then rebuild the heap for the remainder of the *size-1:

1 int*binheapdelete (int**binheap,int*size)2 {3     int*packet = binheap[0]; 4 5binheap[0] = binheap[*size-1]; 6*size--;//This should is (*size)--7Heapify (Binheap, *size,0); 8     return(packet);9}


In the code above, because--and * precedence--are combined right-to-left, so *size--actually reduces the value of the pointer's own value, not the integer it points to. So remember: when you have questions about priorities and bonding, you should use parentheses.


7. Misunderstanding pointer arithmetic (misunderstanding Pointer arithmetic)


The arithmetic operations of pointers are performed in C/s + + in units of the size of the object they point to. For example, the function of the following function is to scan an array of int and return a pointer to the first occurrence of Val:

1 int *search (intint  val)2{3while      (* P && *p = val)4         sizeof(int//  should be p++< /c17>5     return6 }


8. Referencing a non-existent variable (referenceing nonexistent Variables)


If a novice/C + + beginner does not understand the rules of a stack, it may refer to local variables that are no longer valid, such as:

1 int *stackref ()2{3     int4  5     return &6 }


The pointer returned by the function (assuming p) points to a local variable in the stack, but the variable is no longer valid as the STACKREF stack frame is destroyed after the function returns. That is, even though the pointer p returned by the function still points to a valid memory address, it no longer points to a valid variable. When the program subsequently calls other functions, the memory will reuse the memory area where the stack frame was just destroyed. Later, if the program assigns a value to *p, it may actually be modifying the data in another function stack frame, potentially with disastrous and confusing consequences.


9. Referencing the data in the free heap block (referencing. Blocks)


A typical error is referencing data from a heap block that has been freed, for example:

1 int*heapref (intNintm)2 {3     inti;4     int*x, *y;5 6x = (int*)malloc(n *sizeof(int)); 7 8     /* ... */    /*Other calls to malloc and free Go*/9 Ten      Free(x); One  Ay = (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 the  -     returny; -}


10. Causing memory leaks (introducing leaks)


Memory leaks are slow, recessive killers that can occur when programmers forget to release allocated blocks, such as:

 void  Leak (int   N)  2  { 3  int  *x = (int  *) malloc  (n * sizeof  (int   4  5      return ; //  X is garbage at the"  6 }  


If leak is called only a few times throughout the lifetime of the program, the problem is not very serious (but it still wastes memory space) because the operating system reclaims the memory space as the process ends. However, if leak () is called frequently, a serious memory leak will occur, and in the worst case, the entire virtual address space will be consumed. For programs like daemons and servers, memory leaks are serious bugs that must be valued.

Resources


In-depth understanding of computer systems. Bryant & O ' Hallaron.

Common memory operation errors in C programs

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.