简体   繁体   中英

what does it mean to have these kind of errors in C?

this is my solution

#include <stdlib.h>
#include <string.h>

char* deletemultiple(const char* str) {
    if (str == NULL) {
        return NULL; 
    }
    size_t length = strlen(str); 
    if (length == 0) {
        return str; 
    }
    length = length + 1u; 
    char* s = malloc(length); 
    if (s == NULL) {
        return NULL; 
    }  
    size_t j = 0; 
    for (size_t i = 0; s[i] != 0; i++) {
        if (str[i] != str[i+1]) {
            s[j++] = str[i]; 
        }
    }
    s = realloc(s, j+1); 
    if (s == NULL) {
        return NULL; 
    }

    return s; 
}



 int main(void) {
    char str[] = ""; 
    char* s = deletemultiple(str); 

    free(s); 
    return 0; 
} 

it's a program that delete multiple characters (ie adjacent characters) and return a new allocated string without multiple adjacent characters. This solution works only for strings with length != 0; but if string is "" (ie an empty string), when I free the memory, I have an error that blocks the program. (ie A breakpoint instruction (__debugbreak() statement or a similar call) was executed ).

Moreover, I have 2 warnings: one warning reminds me that "realloc might return a null pointer", but I already know that and in fact I've used an if-block to check if it's either null or not.

and the other warning is about "reading invalid data from s, and it's related to this for-loop block:

 for (size_t i = 0; s[i] != 0; i++) {
        if (str[i] != str[i+1]) {
            s[j++] = str[i]; 
        }
    }

can somebody explains what does these errors/warnings mean, and how to solve them? in similar exercises, if I'll have these errors again, what should I do?

If the length is zero, your function is returning its argument, so your code is the same as:

int main(void) {
    char str[] = ""; 
    char* s = str; 
    free(s);  /* ERROR: This is wrong!! */
    return 0; 
} 

but you cannot free(str) , because str was not allocated with malloc .

Just remove the special case check against length zero, and fix your bug so that you allocate length + 1 to leave space for the null terminatorr.

If you passed an empty string then this empty string is returned

char* deletemultiple(const char* str) {
    if (str == NULL) {
        return NULL; 
    }
    size_t length = strlen(str); 
    if (length == 0) {
        return str; 
    }
    //...

So you may not call the function free for such a pointer as you are doing

char* s = deletemultiple(str); 

free(s);

It means that the function interface is broken. You need to return a dynamically allocated empty string.

The dynamically allocated array s does not contain a string because you forgot to append it with the zero terminating character '\0'

If the memory reallocation was not successful

s = realloc(s, j+1); 
if (s == NULL) {
    return NULL; 
}

then the function produces a memory leak because the address of the previously allocated memory that will not be freed in this case will be lost due to reassigning the pointer s . You need to use an intermediate pointer as for example

char *tmp = realloc(s, j+1); 
if (tmp == NULL) {
    free( s );
    return NULL; 
}

The approach when the memory is allocated twice is unsafe. Also it is not required to check whether str is equal to NULL .

if (str == NULL) {
    return NULL; 
}

String functions support the convention according to which if the user passes a null pointer then functions have undefined behavior.

The function can look for example the following way as shown in the demonstration program below.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char * delete_multiple( const char *s ) 
{
    size_t n = strlen( s );

    for ( const char *p = s; *p++; )
    {
        if ( *p == *( p - 1 ) ) --n;
    }

    char *result = malloc( n + 1 );

    if ( result != NULL )
    {
        char *p = result;
        for ( *p = *s; *s++; )
        {
            if ( *s != *p ) *++p = *s;
        }
    }

    return result;
}

int main( void )
{
    char *p = delete_multiple( "" );

    printf( "\"%s\"\n", p );
    free( p );

    p = delete_multiple( "a" );

    printf( "\"%s\"\n", p );
    free( p );
    

    p = delete_multiple( "aa" );

    printf( "\"%s\"\n", p );
    free( p );
    
    p = delete_multiple( "aaa" );

    printf( "\"%s\"\n", p );
    free( p );

    p = delete_multiple( "abaca" );

    printf( "\"%s\"\n", p );
    free( p );
}

The program output is

""
"a"
"a"
"a"
"abaca"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM