C-Еще один выпуск strtok() и free()


Я пытаюсь понять, как полностью освободить память после вызовов strtok(). Я прочитал большинство вопросов, на которые были даны ответы, и ни один из них, казалось, не касался сути моего замешательства. Если это дубликат, не стесняйтесь указывать мне направление чего-то, что отвечает на мой вопрос

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

int main()
{
    char * aliteral = "Hello/world/fine/you";

    char * allocatedstring;

    char * token;
    int i=0;


    allocatedstring=(char *) malloc(sizeof(allocatedstring)*21);
    allocatedstring=strcpy(allocatedstring,aliteral);

    token = strtok(allocatedstring, "/");
    token = strtok(NULL, "/");
    token = strtok(NULL, "/");
    token = strtok(NULL, "/");



    printf("%sn",allocatedstring);
    printf("%sn",token);

    free(allocatedstring);


    return 0;
}

Освобождение allocatedstring здесь освобождает только строку до первого символа , который заменил разделитель strtok. Так что все проясняется только до "Алло". Я проверил это с помощью отладчика eclipse и мониторинг адресов памяти.

Как мне очистить остальную часть? Я попробовал 2 вещи, имея 1 дополнительный указатель на начало allocatedstring и освобождая это (не работает) и освобождая токен после вызова strtok() (тоже не работает)

Так как же мне очистить части allocatedstring, которые теперь находятся между ?

EDIT: чтобы уточнить, видя блоки адресов памяти в отладчике eclipse, я видел строку "HELLO WORLD FINE YOU" в блоках памяти которые изначально были выделены вызовом malloc. После вызова free() блоки, содержащие " HELLO "и первый , превратились в тарабарщину, но остальные блоки сохранили символы"FINE YOU". Я предположил, что это означает, что они не были освобождены.

2 2

2 ответа:

free не имеет представления о \0 завершенных строках.

free освободит то, что было выделено с malloc, и должно работать должным образом в этой ситуации.

Если ваше доказательство того, что free не работает, состоит просто в том, что строковые данные все еще существуют, то вы неправильно понимаете free.
Так и есть нет обнулить память. Он просто помечает его как доступный для использования.
Исходные данные остаются в этой памяти. Но память может быть выделена следующим абонентом malloc, и этот абонент сможет перезаписать ваши данные по своему желанию, потому что вы больше не владеете этими данными!

Если вы хотите очистить эту память (например, если она содержит пароль или ключ безопасности), Вы должны очистить ее с помощью чего-то вроде memset, Прежде чем звонить бесплатно.

Опять же, free только помечает память как "нераспределенную, доступную для использования malloc" и не очищает содержимое.

PS некоторые отладочные системы, такие как Visual Studio, будет перезаписывать освобожденные данные, но только для того, чтобы сделать очевидным в отладчике, что он был освобожден. Такое поведение не требуется по контракту в C, а только помогает в отладке. Как правило, освобожденная память может быть заполнена чем-то вроде 0xdeadbeef.

У вас есть небольшая проблема в этой строке:

allocatedstring=(char *) malloc(sizeof(allocatedstring)*21);

sizeof(allocatedstring) равно sizeof (char *); вы выделяете достаточно места для 21 указателей на char, не 21 символ. Это не проблема, так как char * будет по крайней мере таким же большим, как char, но указывает на некоторую путаницу в том, с какими типами вы имеете дело.

Тем не менее, вам не нужно беспокоиться о размере allocatedstring или *allocatedstring; поскольку вы выделяете достаточно места для хранения литерала, вы можете сделайте следующее:

allocatedstring = malloc( strlen( aliteral ) + 1 ); // note no cast
Что касается поведения, которое вы видите...

free освобождает всю память, связанную с allocatedstring; тот факт, что часть памяти еще не была перезаписана, когда вы проверяли, не удивительно, потому что free не влияет насодержимое этой памяти; она будет содержать все, что было в последний раз записано в нее, пока что-то другое не выделит и не использует ее.