Thread: A mind for program look clear and resource quickly release and easy error process

  1. #31
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Much energy spent but no mind for learning say you. Words and code ridiculous. Image meaningless. Human energy precious rarity in complex world. One angle crazy, another troll.

  2. #32
    Registered User
    Join Date
    Jan 2017
    Posts
    23
    Quote Originally Posted by algorism View Post
    Much energy spent but no mind for learning say you. Words and code ridiculous. Image meaningless. Human energy precious rarity in complex world. One angle crazy, another troll.
    Like above my post in #10,in some angles I think the mind is so very very not much bad,

  3. #33
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    First of all, if you're still using TurboC or some other decades old fossil on DOS/Windows, then you need to get with the times. Your leak detection approach is crude, cumbersome and occasionally ineffective.

    > #define MYDEBUGM1(x) DEBUGTEMP1+=(long long)x;
    > #define MYDEBUGF1(x) DEBUGTEMP1-=(long long)x;
    ...
    > temp3=(struct str1 *)malloc( sizeof(struct str1) );
    ...
    > MYDEBUGM1(temp3)
    Your basic approach is to sum all the pointers, then subtract them again hoping that if the result ends up back at zero, then everything is fine.
    But your big assumption is that numeric overflow doesn't happen, or if it does, that nothing bad happens (like a processor exception).
    If numeric overflow happens, you're assuming that some subset of MYDEBUGF1 calls doesn't result in DEBUGTEMP1 ending up at zero, giving you the false impression that there are no leaks.

    Your further assumption is that pointers can be cast into integers to begin with.
    Quote Originally Posted by c99
    6.3.2.3 Pointers

    6 Any pointer type may be converted to an integer type. Except as previously specified, the
    result is implementation-defined. If the result cannot be represented in the integer type,
    the behavior is undefined. The result need not be in the range of values of any integer
    type.
    Index of /jtc1/sc22/wg14/www/docs/n869
    You really want to be avoiding 'implementation-defined' and 'undefined' behaviour in your code.

    Finally, read this on how to create statement-like macros. Your trailing semicolon (whether present or absent) can lead to some nasty surprises in some cases.
    Don't forget to read the rest of the FAQ.

    Now, if you were using proper tools for the job, you would be using something like valgrind.
    Without editing the code at all, you can get output like this.
    Code:
    $ valgrind ./a.out 
    ==3527== Memcheck, a memory error detector
    ==3527== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==3527== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
    ==3527== Command: ./a.out
    ==3527== 
    Original = 9223372036854775807
         New = 9223372036854775807
    Original = -9223372036854775808
         New = -9223372036854775808
    Original = 0
         New = 0
    Original = 1
         New = 1
    Original = 2
         New = 2
    Original = 3
         New = 3
    Original = 4
         New = 4
    Original = -1
         New = -1
    Original = -2
         New = -2
    Original = -3
         New = -3
    Original = -4
         New = -4
    Original = 9
         New = 9
    Original = 99
         New = 99
    Original = 999
         New = 999
    Original = -9
         New = -9
    Original = -99
         New = -99
    Original = -999
         New = -999
    ==3527== 
    ==3527== HEAP SUMMARY:
    ==3527==     in use at exit: 0 bytes in 0 blocks
    ==3527==   total heap usage: 59 allocs, 59 frees, 1,952 bytes allocated
    ==3527== 
    ==3527== All heap blocks were freed -- no leaks are possible
    ==3527== 
    ==3527== For counts of detected and suppressed errors, rerun with: -v
    ==3527== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    If leaks are detected, it gives you nice file / line numbers of where the leaked memory was allocated.
    Valgrind can also detect other things for you, such as buffer overrun errors and use-after-free errors.

    Even if you don't have valgrind (or expensive commercial tools on windows), you can still make a much better job than manually having to edit the code every time you call malloc or free.
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<limits.h>
    
    #ifdef MY_CRUDE_LEAKCHECK
    void *myMalloc(const char *file, int line, size_t size ) {
      void *mem = malloc(size);
      fprintf(stderr,"%p allocated to %s:%d\n", mem, file, line);
      return mem;
    }
    void myFree(const char *file, int line, void *mem ) {
      free(mem);
      fprintf(stderr,"%p released  by %s:%d\n", mem, file, line);
    }
    
    #define malloc(x) myMalloc(__FILE__,__LINE__,x)
    #define free(x)   myFree(__FILE__,__LINE__,x)
    #endif
    
    struct str1 {
      unsigned char thevalue;
      struct str1 *theprior;
    };
    typedef struct str1 llnode;
    
    llnode *newNode(unsigned char value, llnode *next) {
      llnode *n = malloc( sizeof(*n) );
      if ( n ) {
        n->thevalue = value;
        n->theprior = next;
      }
      return n;
    }
    
    void freeNodes(llnode *head) {
      while ( head != NULL ) {
        llnode *next = head->theprior;
        free(head);
        head = next;
      }
    }
    
    void printNodes(llnode *head) {
      while ( head != NULL ) {
        putchar(head->thevalue+'0');
        head = head->theprior;
      }
    }
    
    void printll2(long long arg) {
      if ( arg == 0 ) {
        putchar('0');
      } else {
        llnode *list = NULL;
        int negFlag = 0;
        if ( arg < 0 ) {
          negFlag = 1;
          if ( arg == LLONG_MIN ) {
            // negating most negative number is numeric overflow in 2's complement - careful!
            long long temp = (arg+1)*-1;
            unsigned char c = temp % 10;
            c = c == 9 ? 0 : c+1; // undo the +1 hack at negation
            list = newNode(c,NULL);
            arg = temp / 10;
          } else {
            arg *= -1;
            list = newNode(arg % 10,NULL);
            arg /= 10;
          }
        } else {
          list = newNode(arg % 10,NULL);
          arg /= 10;
        }
        while ( arg != 0 ) {
          list = newNode(arg%10,list);
          arg /= 10;
        }
        if ( negFlag ) putchar('-');
        printNodes(list);
        freeNodes(list);
      }
    }
    
    int main(int argc, char *argv[])
    {
      long long tests[] = {
        LLONG_MAX, LLONG_MIN, 
        0,
        +1, +2, +3, +4,
        -1, -2, -3, -4,
        +9, +99, +999,
        -9, -99, -999,
      };
      size_t i;
      for ( i = 0 ; i < sizeof(tests)/sizeof(*tests) ; i++ ) {
        printf("Original = %lld\n", tests[i] );
        printf("     New = " );
        printll2(tests[i]);
        printf("\n");
      }
      return 0;
    }
    
    
    $ gcc -DMY_CRUDE_LEAKCHECK -Wall -g foo.c
    $ ./a.out 
    Original = 9223372036854775807
    <<snipped verbosity>>
         New = 9223372036854775807
    Original = -9223372036854775808
    <<snipped verbosity>>
         New = -9223372036854775808
    Original = 0
         New = 0
    Original = 1
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 1
    Original = 2
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 2
    Original = 3
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 3
    Original = 4
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 4
    Original = -1
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -1
    Original = -2
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -2
    Original = -3
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -3
    Original = -4
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -4
    Original = 9
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 9
    Original = 99
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = 99
    Original = 999
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2460 allocated to foo.c:27
    0x6d2460 released  by foo.c:38
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = 999
    Original = -9
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -9
    Original = -99
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = -99
    Original = -999
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2460 allocated to foo.c:27
    0x6d2460 released  by foo.c:38
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = -999
    Here are some things for you to study and take note of.
    1. There aren't any goto statements.
    2. Note the use of small utility functions to encapsulate repeated behaviour. See how my printll2 is only 30 lines long, compared to your printll function is way over 100 lines long.
    3. The leak check macros can be switched in and out with a simple command line switch, and NO editing of the real source code is required.
    4. The output of the leak check macros could be redirected to either memory (as a separate memory tracking data structure), or to a file (for post-run analysis).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #34
    Registered User
    Join Date
    Jan 2017
    Posts
    23
    Quote Originally Posted by Salem View Post
    First of all, if you're still using TurboC or some other decades old fossil on DOS/Windows, then you need to get with the times. Your leak detection approach is crude, cumbersome and occasionally ineffective.

    > #define MYDEBUGM1(x) DEBUGTEMP1+=(long long)x;
    > #define MYDEBUGF1(x) DEBUGTEMP1-=(long long)x;
    ...
    > temp3=(struct str1 *)malloc( sizeof(struct str1) );
    ...
    > MYDEBUGM1(temp3)
    Your basic approach is to sum all the pointers, then subtract them again hoping that if the result ends up back at zero, then everything is fine.
    But your big assumption is that numeric overflow doesn't happen, or if it does, that nothing bad happens (like a processor exception).
    If numeric overflow happens, you're assuming that some subset of MYDEBUGF1 calls doesn't result in DEBUGTEMP1 ending up at zero, giving you the false impression that there are no leaks.

    Your further assumption is that pointers can be cast into integers to begin with.

    Index of /jtc1/sc22/wg14/www/docs/n869
    You really want to be avoiding 'implementation-defined' and 'undefined' behaviour in your code.

    Finally, read this on how to create statement-like macros. Your trailing semicolon (whether present or absent) can lead to some nasty surprises in some cases.
    Don't forget to read the rest of the FAQ.

    Now, if you were using proper tools for the job, you would be using something like valgrind.
    Without editing the code at all, you can get output like this.
    Code:
    $ valgrind ./a.out 
    ==3527== Memcheck, a memory error detector
    ==3527== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==3527== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
    ==3527== Command: ./a.out
    ==3527== 
    Original = 9223372036854775807
         New = 9223372036854775807
    Original = -9223372036854775808
         New = -9223372036854775808
    Original = 0
         New = 0
    Original = 1
         New = 1
    Original = 2
         New = 2
    Original = 3
         New = 3
    Original = 4
         New = 4
    Original = -1
         New = -1
    Original = -2
         New = -2
    Original = -3
         New = -3
    Original = -4
         New = -4
    Original = 9
         New = 9
    Original = 99
         New = 99
    Original = 999
         New = 999
    Original = -9
         New = -9
    Original = -99
         New = -99
    Original = -999
         New = -999
    ==3527== 
    ==3527== HEAP SUMMARY:
    ==3527==     in use at exit: 0 bytes in 0 blocks
    ==3527==   total heap usage: 59 allocs, 59 frees, 1,952 bytes allocated
    ==3527== 
    ==3527== All heap blocks were freed -- no leaks are possible
    ==3527== 
    ==3527== For counts of detected and suppressed errors, rerun with: -v
    ==3527== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    If leaks are detected, it gives you nice file / line numbers of where the leaked memory was allocated.
    Valgrind can also detect other things for you, such as buffer overrun errors and use-after-free errors.

    Even if you don't have valgrind (or expensive commercial tools on windows), you can still make a much better job than manually having to edit the code every time you call malloc or free.
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<limits.h>
    
    #ifdef MY_CRUDE_LEAKCHECK
    void *myMalloc(const char *file, int line, size_t size ) {
      void *mem = malloc(size);
      fprintf(stderr,"%p allocated to %s:%d\n", mem, file, line);
      return mem;
    }
    void myFree(const char *file, int line, void *mem ) {
      free(mem);
      fprintf(stderr,"%p released  by %s:%d\n", mem, file, line);
    }
    
    #define malloc(x) myMalloc(__FILE__,__LINE__,x)
    #define free(x)   myFree(__FILE__,__LINE__,x)
    #endif
    
    struct str1 {
      unsigned char thevalue;
      struct str1 *theprior;
    };
    typedef struct str1 llnode;
    
    llnode *newNode(unsigned char value, llnode *next) {
      llnode *n = malloc( sizeof(*n) );
      if ( n ) {
        n->thevalue = value;
        n->theprior = next;
      }
      return n;
    }
    
    void freeNodes(llnode *head) {
      while ( head != NULL ) {
        llnode *next = head->theprior;
        free(head);
        head = next;
      }
    }
    
    void printNodes(llnode *head) {
      while ( head != NULL ) {
        putchar(head->thevalue+'0');
        head = head->theprior;
      }
    }
    
    void printll2(long long arg) {
      if ( arg == 0 ) {
        putchar('0');
      } else {
        llnode *list = NULL;
        int negFlag = 0;
        if ( arg < 0 ) {
          negFlag = 1;
          if ( arg == LLONG_MIN ) {
            // negating most negative number is numeric overflow in 2's complement - careful!
            long long temp = (arg+1)*-1;
            unsigned char c = temp % 10;
            c = c == 9 ? 0 : c+1; // undo the +1 hack at negation
            list = newNode(c,NULL);
            arg = temp / 10;
          } else {
            arg *= -1;
            list = newNode(arg % 10,NULL);
            arg /= 10;
          }
        } else {
          list = newNode(arg % 10,NULL);
          arg /= 10;
        }
        while ( arg != 0 ) {
          list = newNode(arg%10,list);
          arg /= 10;
        }
        if ( negFlag ) putchar('-');
        printNodes(list);
        freeNodes(list);
      }
    }
    
    int main(int argc, char *argv[])
    {
      long long tests[] = {
        LLONG_MAX, LLONG_MIN, 
        0,
        +1, +2, +3, +4,
        -1, -2, -3, -4,
        +9, +99, +999,
        -9, -99, -999,
      };
      size_t i;
      for ( i = 0 ; i < sizeof(tests)/sizeof(*tests) ; i++ ) {
        printf("Original = %lld\n", tests[i] );
        printf("     New = " );
        printll2(tests[i]);
        printf("\n");
      }
      return 0;
    }
    
    
    $ gcc -DMY_CRUDE_LEAKCHECK -Wall -g foo.c
    $ ./a.out 
    Original = 9223372036854775807
    <<snipped verbosity>>
         New = 9223372036854775807
    Original = -9223372036854775808
    <<snipped verbosity>>
         New = -9223372036854775808
    Original = 0
         New = 0
    Original = 1
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 1
    Original = 2
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 2
    Original = 3
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 3
    Original = 4
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 4
    Original = -1
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -1
    Original = -2
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -2
    Original = -3
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -3
    Original = -4
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -4
    Original = 9
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = 9
    Original = 99
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = 99
    Original = 999
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2460 allocated to foo.c:27
    0x6d2460 released  by foo.c:38
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = 999
    Original = -9
    0x6d2420 allocated to foo.c:27
    0x6d2420 released  by foo.c:38
         New = -9
    Original = -99
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = -99
    Original = -999
    0x6d2420 allocated to foo.c:27
    0x6d2440 allocated to foo.c:27
    0x6d2460 allocated to foo.c:27
    0x6d2460 released  by foo.c:38
    0x6d2440 released  by foo.c:38
    0x6d2420 released  by foo.c:38
         New = -999
    Here are some things for you to study and take note of.
    1. There aren't any goto statements.
    2. Note the use of small utility functions to encapsulate repeated behaviour. See how my printll2 is only 30 lines long, compared to your printll function is way over 100 lines long.
    3. The leak check macros can be switched in and out with a simple command line switch, and NO editing of the real source code is required.
    4. The output of the leak check macros could be redirected to either memory (as a separate memory tracking data structure), or to a file (for post-run analysis).
    The overflow is a big problem that I always and still think to slove,I think it is a difficulty to many software design work like database, the print long long int type program is use to show the mind mostly,
    My mind mostly is to work mostly use C language use the code "style" not other lot of languages,to spend many many energy to the very very important things,The world many many human,less less resources,like hair is burning,put water and so on is a stringency demand.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lnk 2005 error in release only
    By harryGrat in forum Windows Programming
    Replies: 1
    Last Post: 02-11-2009, 09:41 AM
  2. release resource for WebClient class
    By George2 in forum C# Programming
    Replies: 1
    Last Post: 06-02-2008, 01:14 PM
  3. is there easy way to clear nested vector?
    By timchen in forum C++ Programming
    Replies: 1
    Last Post: 12-26-2007, 10:18 PM
  4. MFC: LineDraw Release Error
    By mrafcho001 in forum Windows Programming
    Replies: 1
    Last Post: 06-25-2005, 10:24 AM
  5. my very cool new program has a mind boggling probem!!!
    By face_master in forum C++ Programming
    Replies: 11
    Last Post: 12-20-2001, 04:37 PM

Tags for this Thread