Czy istnieje sposób (w czystym C), aby odróżnić malloced ciąg z ciągiem dosłownym,
Nie w każdym przenośnym sposób, no. Nie musisz się jednak martwić; istnieją lepsze alternatywy.
Kiedy piszesz kod w C, robisz to, jednocześnie robiąc silne gwarancje "kto" jest właścicielem pamięci. Czy dzwoniący jest właścicielem? Wtedy ich obowiązkiem jest zwolnić go. Czy właściciel jest właścicielem? Podobna rzecz.
Piszesz kod, który jasno określa łańcuch kontroli i prawo własności i nie napotykasz problemów takich jak "kto zwalnia?" Nie powinieneś czuć potrzeby, aby powiedzieć:
// after many, many lines of code an algorithmic branches...
// now I forgot about s3: was it assigned to s1 or s2?
Rozwiązaniem jest; nie zapomnij! Masz kontrolę nad swoim kodem, po prostu spójrz trochę na stronę. Zaprojektuj go tak, aby był odporny na kulki, przed wypuszczeniem pamięci do innych funkcji bez wyraźnego zrozumienia, że "hej, możesz to przeczytać, ale nie ma gwarancji, że będzie on ważny po X lub Y. To nie jest twoja pamięć, traktuj to jako takie . "
A może to twoja pamięć. Przykładem; twój telefon do strdup
. strdup
załóżmy, że (poprzez dokumentację) Twoim obowiązkiem jest zwolnić ciąg, który ci zwraca. Sposób, w jaki to robisz, zależy od ciebie, ale najlepiej jest ograniczyć jego zakres tak, aby był tak wąski, jak to możliwe, i utrzymywać go tylko przez tak krótki czas, jak to konieczne.
Potrzeba czasu i praktyki, aby stać się drugą naturą. Stworzysz kilka projektów, które poradzą sobie z pamięcią słabo, zanim się poprawisz. W porządku; twoje błędy na początku nauczą cię, co dokładnie zrobić, a unikniesz powtórzenia ich w przyszłości (miejmy nadzieję!).
Również, jak @Lasse nawiązywał do komentarzy, nie masz martwić się o s3
, który jest kopią wskaźnika, a nie całą porcją pamięci. Jeśli zadzwonisz za darmo na s2
i s3
, otrzymasz nieokreślone zachowanie.
Nie w żaden przenośny sposób, nie. Dlaczego tak trzeba? Wygląda na to, że próbujesz zarządzać pamięcią w niewłaściwy sposób. Istnieją lepsze sposoby na zagwarantowanie, że pamięć jest przydzielana i prawidłowo czyszczona. Pierwszym krokiem jest nie "zapomnieć", jak coś zostało przydzielone. –
Nie jestem programistą C/C++, ale wydaje mi się to oczywiste, więc prawdopodobnie czegoś mi brakuje. W każdym razie, jeśli potrzebujesz zwolnić 's2', czy w ogóle troszczycie się o' s3', jeśli ma zostać przypisana wartość 's1' lub' s2', i nic więcej? Nie uwolnisz dwa razy ciągu zwróconego przez 'strdup', więc jeśli masz zamiar zwolnić' s2', dlaczego interesuje Cię 's3'? –
Kiedy piszesz kod w C, robisz to podczas robienia silnych gwarancji "kto" jest właścicielem pamięci. Czy dzwoniący jest właścicielem? Wtedy ich obowiązkiem jest zwolnić go. Czy właściciel jest właścicielem? Podobna rzecz. Piszesz kod, który jasno mówi o łańcuchu nadzoru i własności, i nie napotykasz problemów takich jak "kto zwalnia to?" I, jak powiedział Lasse, jeśli nazwiesz 'free' na' s2' * i * 's3', skończysz z niezdefiniowanym zachowaniem. –