为什么指向字符串文字

时间:2015-08-21 16:04:22

标签: c

关于我的问题有一些相关的讨论,但对我的问题没有明确的解释。

我认为我必须free()无论我malloc(),无论何时何地,但我必须这样做,以防止内存泄漏。 所以我有以下计划:

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

int main(void)
{
    int *ptr;

    ptr = malloc(256);

    if (ptr == NULL)    {
        printf("Out of memory\n");
        return 1;
    }

    *ptr = 10;

    printf("The value of PTR is:\t%d\n",*ptr);
    free(ptr);

    return 0;
}

我有一个指针,我动态分配了一些内存(256),然后我检查了NULL字母free()

直到这里一切正常:指针被动态分配了一些内存然后我free()它。

现在我将使用一个字符指针,在我将动态分配一些内存(256)之后,我会将该指针指向一个字符串文字,让我们说MICHI:

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

int main(void)
{
    char *ptr;

    ptr = malloc(256);

    if (ptr == NULL)    {
        printf("Out of memory\n");
        return 1;
    }

    ptr = "michi";
    printf("%s",ptr);

    free(ptr);

    return 0;
}

我在做错了,因为如果我尝试free()它,那么它就行不通,因为它发生了我将要释放一个非堆对象。

所以我迷失在这里,因为我认为你malloc()所有的一切都需要free()。 在指向字符串文字之后,究竟是什么使该指针不需要free() ed

5 个答案:

答案 0 :(得分:5)

 ptr = malloc(256);
 ...
 ptr = "michi";
 printf("%s",ptr);
 free(ptr);

当你将内存分配给ptr然后你指向string literal时。因此,指针ptr不再指向由malloc分配的内存。

free未分配malloc或类似功能的 strcpy(ptr,"michi"); 内存导致程序错误。

这样做 -

private int CalcSlide(int first, int last, HashSet<long> numbers)
{
  if (last < first)
    return 0;

  // Strategy:
  // running over the input numbers, in ordered fashion from below, we'll scan an "appropriate" sliding window
  // in that same collection to see if we find any sums that we didn't find before.
  // We start out with the lowest number as an "anchor" and determine the HIGHEST number that might be relevant,
  // i.e. that will not sum to beyond "last".
  // Saving that separately, for later use, we scan down until we sum (always with the "anchor") to below "first".
  //
  // We maintain the sums-to-be-found in a hash.
  // As soon as our scan hits a yet-to-be-found sum, we remove it from the hash and update first/last as appropriate.
  // Having completed this cycle we increase the anchor, redetermine the hightest relevant number to start a new scan,
  // (this redetermination starts at the saved previous value, walking down), and then we scan again.
  // Exits occur whever the obvious conditions are fullfilled: there's nothing left to search for, we've nothing left to scan.
  //
  // Time-complexity:
  // Given an input hash set we first construct a sorted array from that: O(nLogn)
  // The subsequent sliding-window-scan procedure is O(N) if we look at scnario's with N (the number of input points) being much larger
  // than the range of sums-to-find. More precisely the worst-case behaviour is O(N M logM), where M is the range of sums to find.
  // (It would be somewhat difficult to construct an scenario where we really have such "worst case behaviour").
  // 1. Obviously, the "outer loop" over the anchor is just "from 1 to N".
  // 2. Computing the upperbound of the scan, for each anchor again, is also linear: it just runs from N-1 down to the anchor
  //    (in separate strides for each anchor).
  // 3. The scan, at each round, is somewhat more complicated. It is potentially long - over all numbers down to the anchor.
  //    However, since all numbers are different (coming from a hashset), the scanwindow can never be larger than the range of sums (yet) to find.
  //    The worst-case behaviour is then O(N*MlogM), where the logM factor arises from having to search for a sum in the hashSet of sums.
  //    Of course, as we find "some" sums on the way, both the search-in-sumHashSet diminishes and the scanwindow gets smaller whenever we find
  //    the current "first" or "last".

  int sumCountOriginal = last - first + 1;

  // Get a sorted array from the provided numbers.
  long[] sortedSet = new long[this.HNumbers.Count];
  int j = 0;
  foreach (long value in HNumbers)
    sortedSet[j++] = value;
  Array.Sort(sortedSet);

  // Create a (relatively small) HashSet from the sums sought.
  // This serves to easily remove items that we find, and then verify if there are any left.
  HashSet<int> HSums = new HashSet<int>();
  for (int sum = first; sum <= last; ++sum)
    HSums.Add(sum);

  int N = sortedSet.Length;

  int jLow = 0;
  int jScanStart = sortedSet.Length - 1;

  while (HSums.Count > 0)
  {
    long xLow = sortedSet[jLow];
    long xScan = sortedSet[jScanStart];

    // decrease jScanStart to get maxSum or less.
    while (jScanStart > jLow + 1 && xScan + xLow > last)
      xScan = sortedSet[--jScanStart];

    // scan until we get below minSum.
    int jScan = jScanStart;
    while (jScan > jLow && xLow + xScan >= first)
    {
      int sum = (int)(xLow + xScan);
      if (HSums.Contains(sum))
      {
        HSums.Remove(sum);

        if (sum == last)
          while (last >= first && !HSums.Contains(last))
            last--;

        if (sum == first)
          while (first <= last && !HSums.Contains(first))
            first++;

        if (last < first)
          return sumCountOriginal;
      }

      xScan = sortedSet[--jScan];
    } // scan

    // next xLow.
    if (++jLow == N - 1 || jScanStart <= jLow)
      return sumCountOriginal - HSums.Count;

  } // there are still unresolved sums.

  // unexpected fall-thru - we should never get here.
  return sumCountOriginal - HSums.Count;
}

答案 1 :(得分:4)

在第一个程序中你分配了内存

ptr = malloc(256);

并初始化其第一个sizeof( int )字节,整数值为10。

*ptr = 10;

指针本身没有改变。所以在这个声明中

free(ptr);

指针ptr指向使用malloc分配的内存。

在第二个程序中,您以与第一个程序

相同的方式分配了内存
ptr = malloc(256);

但是后来你用字符串文字“michi”的第一个字符的地址重新指定了指针本身

ptr = "michi";

比较此作业的左侧

*ptr = 10;

和这项任务

ptr = "michi";

如你所见,他们是不同的。在第一种情况下,您正在更改已分配的内存,而在第二种情况下,您正在更改指针本身。

因此在本声明中

free(ptr);

指针ptr未指向先前分配的内存。它指向未使用malloc分配的字符串文字所占用的内存。

因此这个语句是错误的并且程序有内存泄漏,因为使用malloc分配的先前内存未被释放,

答案 2 :(得分:3)

因为常量文字以一种方式存储在程序的生命周期中,所以在大多数平台的只读内存区域中。

当你使用free时,你试图释放分配的内存,而不是指针本身,这就是为什么如果你试图在一个只读的内存区域中这样做就不会有效

当您重新分配指针时,您将丢失已分配内存的跟踪,从而导致内存泄漏。 创建内存泄漏是因为您首先分配了内存并将其分配给指针,当您指向它时,您可以轻松释放该内存,但是当您没有任何对该内存的引用时,您可以'吨。 这就是正在发生的事情,当将文字分配给指针时,不再有对该地址的引用,它已被分配,但它不再可用,这样就无法释放内存。

答案 3 :(得分:1)

问题是你在指定了另一个值的第二个指针丢失了指针:

ptr = malloc(256);

if (ptr == NULL)    {
    printf("Out of memory\n");
    return 1;
}

// here you should free your memory
ptr = "michi";
printf("%s",ptr);

// this fails, because ptr now points to the const static string "michi" you have coded yourself. The assignment didn't copy it, just changed what ptr points to.
free(ptr);

答案 4 :(得分:0)

试试这个。

#include <stdio.h>

int main(void)
{
     char   *str:

     str = (char*)malloc(sizeof(str) * 4);
     printf("Addr of str before: %p\n", str);
     str = "Joe";
     printf("Addr of str after: %p\n",str);
     return(0);
} 

/ *您将获得以下地址:

之前的str的地址:0x51fc040 str后面的地址:0x4006f0

这是因为你改变了str指向的地方。 0x51fc040是使用malloc分配的内存,0x4006f0是字符串文字“Joe”的内存地址。

我会建议以下...... * /

#include <stdio.h>

int main(void)
{
     char    *str;

     str = (char*)malloc(sizeof(str) * 4);
     printf("Addr of str before: %p\n", str); 
     str =strncpy(str, "Joe", 4);
     printf("Addr of str after: %p\n",str);
     free(str);
     return (0);
}

/ *您将获得以下地址:

之前的str的地址:0x51fc040 str的地址:0x51fc040

这是因为strncpy将字符串文字复制到动态分配的内存中。它比stcpy更安全,因为它可以防止缓冲区溢出