如何使用malloc和free进行动态内存分配

时间:2017-02-08 12:42:48

标签: c malloc

我刚开始学习C,来自php。我还不明白如何使用malloc和free。

1)在下面的示例代码中,我可以将“免费”放在哪里?

valgrind ./reverse Text ONe
==3124== Memcheck, a memory error detector
==3124== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3124== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==3124== Command: ./reverse Text ONe
==3124==
==3124== Invalid write of size 1
==3124==    at 0x40060F: reverse (in /localServer/temp/C/reverse)
==3124==    by 0x400654: main (in /localServer/temp/C/reverse)
==3124==  Address 0x5203044 is 0 bytes after a block of size 4 alloc'd
==3124==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3124==    by 0x4005C6: reverse (in /localServer/temp/C/reverse)
==3124==    by 0x400654: main (in /localServer/temp/C/reverse)
==3124==
==3124== Invalid read of size 1
==3124==    at 0x4E88CC0: vfprintf (vfprintf.c:1632)
==3124==    by 0x4E8F898: printf (printf.c:33)
==3124==    by 0x400682: main (in /localServer/temp/C/reverse)
==3124==  Address 0x5203044 is 0 bytes after a block of size 4 alloc'd
==3124==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3124==    by 0x4005C6: reverse (in /localServer/temp/C/reverse)
==3124==    by 0x400654: main (in /localServer/temp/C/reverse)
==3124==
1 Text  txeT
2 ONe eNO
==3124==
==3124== HEAP SUMMARY:
==3124==     in use at exit: 7 bytes in 2 blocks
==3124==   total heap usage: 3 allocs, 1 frees, 1,031 bytes allocated
==3124==
==3124== LEAK SUMMARY:
==3124==    definitely lost: 7 bytes in 2 blocks
==3124==    indirectly lost: 0 bytes in 0 blocks
==3124==      possibly lost: 0 bytes in 0 blocks
==3124==    still reachable: 0 bytes in 0 blocks
==3124==         suppressed: 0 bytes in 0 blocks
==3124== Rerun with --leak-check=full to see details of leaked memory
==3124==
==3124== For counts of detected and suppressed errors, rerun with: -v
==3124== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 0 from 0)

2)这是valgrind的输出。什么意思错误“无效写入大小1”和“无效读取大小1”?

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/single_message_view">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="wrap_content"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="author"
            android:id="@+id/sender_data"
            android:layout_marginEnd="5dp"
            android:textColor="@color/colorWhite" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_weight="1"
            android:textAlignment="textEnd"
            android:layout_height="wrap_content"
            android:text="date"
            android:textColor="@color/colorWhite"
            android:id="@+id/send_date" />

    </LinearLayout>

<LinearLayout
    android:layout_marginEnd="15dp"
    android:layout_marginStart="15dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minWidth="100dp"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:id="@+id/message_content"
        android:background="@drawable/msg_haze"
        >

        <TextView
            android:layout_margin="10dp"
            android:layout_alignParentTop="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/colorWhite"
            android:id="@+id/message_text"
            android:text="content" />

        <LinearLayout
            android:layout_margin="10dp"
            android:minWidth="100dp"
            android:layout_below="@id/message_text"
            android:id="@+id/tags_container"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.RecyclerView
                android:layout_marginTop="5dp"
                android:layout_marginBottom="5dp"
                android:id="@+id/message_tags"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layoutManager="LinearLayoutManager"
                tools:listitem="@layout/item_tag" />
        </LinearLayout>

        <ImageView
            android:layout_marginBottom="10dp"
            android:layout_marginEnd="10dp"
            android:paddingBottom="10dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentBottom="true"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:id="@+id/message_state" />

        <LinearLayout
            android:id="@+id/attachment_holder"
            android:layout_marginTop="10dp"
            android:padding="5dp"
            android:visibility="gone"
            android:orientation="vertical"
            android:layout_alignParentBottom="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/attachments_haze">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/attachments"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layoutManager="GridLayoutManager"/>

            <ImageView
                android:id="@+id/attachment"
                android:visibility="gone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>

    </RelativeLayout>
</LinearLayout>

谢谢。

2 个答案:

答案 0 :(得分:3)

在使用反向返回的指针后,你应该在循环中释放,如下所示。

int main (int argc, char** argv) {
    char *reverseStrPtr;

    if (argc > 1) {
        for (int i = 1; i < argc; ++i) {
            reverseStrPtr = reverse(argv[i]);
            printf("%d\t%s\t%s\n", i, argv[i], reverseStrPtr); 
            free(reverseStrPtr);
        }
    }

    return 0;
}

此外,valgrind错误基于下面的行reverse

t[count] = '\0'; /* Add end of string */

简单地说,当你分配count-many字节时,你的索引范围是[0, count)。因此,尝试访问计数等同于访问(count+1)位,这是访问冲突。

您需要纠正的是您分配的内存量,即(count+1)个字节。需要额外的字节来放置终止'\0'字符。

char* reverse(char* text) {
    int count = strLen(text);
    char* t = malloc(count+1); // +1 for the terminating '\0'

    for (int i = count; i > 0; --i) { t[count - i] = text[i-1];}
    t[count] = '\0'; /* Add end of string */

    return t;
}

答案 1 :(得分:1)

您需要保留从reverse(argv[i])free返回的指针。

一种方法是将main略微调整为

int main (int argc, char** argv) {
    char* s;

    // if (argc > 1) { Comment out the redundant check
        for (int i = 1; i < argc; ++i) { 
            printf("%d\t%s\t%s\n", i, argv[i], s = reverse(argv[i]));
            free(s); 
        }
    //}
    return 0;
}

表达式内的赋值不是每个人的口味(因为它们可以混淆),但它们在这样的实例中运行良好。我应该习惯于在C中习惯这样的事情。

此外,t[count] = '\0';超出了您的缓冲区 - 其行为是 undefined 。您需要malloc(1 + count);