原始堆字符串

时间:2016-05-03 20:46:18

标签: c

我试图围绕C语言中的堆管理概念。以下代码编译没有警告并且没有错误运行。

Image: /Users/deathstroke/Desktop/lipRead/VidTIMIT/mwbt0/video/sx383/roi081.jpeg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Class: DirectClass
  Geometry: 68x39+0+0
  Units: Undefined
  Type: TrueColor
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
  Channel statistics:
    Pixels: 2652
    Red:
      min: 0 (0)
      max: 223 (0.87451)
      mean: 139.207 (0.54591)
      standard deviation: 44.1822 (0.173263)
      kurtosis: 0.798663
      skewness: -1.01178
      entropy: 0.942718
    Green:
      min: 0 (0)
      max: 159 (0.623529)
      mean: 87.1161 (0.341632)
      standard deviation: 33.4156 (0.131041)
      kurtosis: -0.162594
      skewness: -0.485596
      entropy: 0.955489
    Blue:
      min: 0 (0)
      max: 249 (0.976471)
      mean: 73.9367 (0.289948)
      standard deviation: 43.7079 (0.171403)
      kurtosis: 2.38585
      skewness: 1.43844
      entropy: 0.917047
  Image statistics:
    Overall:
      min: 0 (0)
      max: 249 (0.976471)
      mean: 100.087 (0.392496)
      standard deviation: 40.7392 (0.159761)
      kurtosis: 2.09684
      skewness: 0.445232
      entropy: 0.938418
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: white
  Border color: srgb(223,223,223)
  Matte color: grey74
  Transparent color: black
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 68x39+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  Quality: 95
  Orientation: Undefined
  Properties:
    date:create: 2016-04-15T23:19:32+06:00
    date:modify: 2016-04-15T23:19:32+06:00
    jpeg:colorspace: 2
    jpeg:sampling-factor: 2x2,1x1,1x1
    signature: d3f2c14b57043efd4edbf719dfe769aded504df16c5b9fc8ee436d7551993221
  Artifacts:
    filename: /Users/deathstroke/Desktop/lipRead/VidTIMIT/mwbt0/video/sx383/roi081.jpeg
    verbose: true
  Tainted: False
  Filesize: 1.81KB
  Number pixels: 2.65K
  Pixels per second: 265KB
  User time: 0.000u
  Elapsed time: 0:01.009
  Version: ImageMagick 6.9.3-7 Q16 x86_64 2016-03-27 http://www.imagemagick.org

我有几个问题:

  1. string_make()做了什么非法或未定义的事吗?
  2. string_concat()是否做了非法或未定义的事情?
  3. 我只是想创建一个简单的堆字符串,可以根据需要在程序的不同阶段增加/减少。

    感谢。

    编辑:

    如果我将main中的string_concat()调用更改为以下内容:

    char* string_make(char* text) {
          size_t len = strlen(text) + 1;
          char* str = malloc(len);
          memcpy(str, text, len);
          return str;
    }
    
    char* string_concat(char* x, char* y) {
          size_t len_x = strlen(x);
          size_t len_y = strlen(y);
          x = realloc(x, len_x + len_y + 1);
          memcpy(x+len_x, y, len_y+1);
          return x;
    }
    
    int main (int argc, char const *argv[]) {
          char* first = string_make("funny");
          char* second = string_make(" duck");
          char* third = string_make("! c++");
          //
          printf("%s\n", string_concat(first, second));
          printf("%s\n", string_concat(first, third));
          //
          free(first);
          free(second);
          free(third);
    }
    
    它会让事情变得合法吗?

3 个答案:

答案 0 :(得分:3)

string_make很好。

string_concat不是。它重新分配x,这可能意味着在其他地方分配了更大的内存块,并且原始内存块被标记为空闲。但是,C中的函数不会更改其参数,因此当string_concat返回时,x可能指向标记为free的位置。

答案 1 :(得分:2)

忽略错误检查(在mallocrealloc之后),您需要做的只是在main中替换这两行:

printf("%s\n", string_concat(first, second));
printf("%s\n", string_concat(first, third));

这些行

first = string_concat(first, second);    
printf("%s\n", first);
first = string_concat(first, third);
printf("%s\n", first);

原因是参数是按C中的值传递的。因此,更新x中的string_concat不会更新first中的变量main。所以代码需要使用函数的返回值来更新first

现在,您可能会感到困惑,因为您测试了代码并且它似乎有效。那是因为你的最后一个字符串只有16个字节,包括NUL终结符。 malloc的大多数现代实现都会将大小四舍五入为16的倍数(或者更大的2的幂)。这意味着对string_make的所有三次调用都返回指向16字节内存区域的指针,即使您请求的更少。这也意味着realloc可以在不移动缓冲区的情况下扩展缓冲区。正如手册页解释

  

如果没有足够的空间来扩大内存分配   由ptr指出,realloc()创建一个新的分配,复制尽可能多   ptr指向的旧数据将适合新的分配,   释放旧的分配,并返回指向已分配的指针   存储器中。

在你的情况下, 有足够的空间来扩大内存分配,因此realloc返回了传入的相同指针。结果,你的代码似乎工作了即使它有严重的缺陷。

答案 2 :(得分:0)

donuts_plot <- function( panel = runif(3), # counts pctr = c(.5,.2,.9), # percentage in count legend.label='', cols = c('chartreuse', 'chocolate','deepskyblue'), # colors outradius = 1, # outter radius radius = .7, # 1-width of the donus add = F, innerradius = .5, # innerradius, if innerradius==innerradius then no suggest line legend = F, pilabels=F, legend_offset=.25, # non-negative number, legend right position control borderlit=c(T,F,T,T) ){ par(new=add) if(sum(legend.label=='')>=1) legend.label=paste("Series",1:length(pctr)) if(pilabels){ pie(panel, col=cols,border = borderlit[1],labels = legend.label,radius = outradius) } panel = panel/sum(panel) pctr2= panel*(1 - pctr) pctr3 = c(pctr,pctr) pctr_indx=2*(1:length(pctr)) pctr3[pctr_indx]=pctr2 pctr3[-pctr_indx]=panel*pctr cols_fill = c(cols,cols) cols_fill[pctr_indx]='white' cols_fill[-pctr_indx]=cols par(new=TRUE) pie(pctr3, col=cols_fill,border = borderlit[2],labels = '',radius = outradius) par(new=TRUE) pie(panel, col='white',border = borderlit[3],labels = '',radius = radius) par(new=TRUE) pie(1, col='white',border = borderlit[4],labels = '',radius = innerradius) if(legend){ # par(mar=c(5.2, 4.1, 4.1, 8.2), xpd=TRUE) legend("topright",inset=c(-legend_offset,0),legend=legend.label, pch=rep(15,'.',length(pctr)), col=cols,bty='n') } par(new=FALSE) } ## col- > subcor(change hue/alpha) subcolors <- function(.dta,main,mainCol){ tmp_dta = cbind(.dta,1,'col') tmp1 = unique(.dta[[main]]) for (i in 1:length(tmp1)){ tmp_dta$"col"[.dta[[main]] == tmp1[i]] = mainCol[i] } u <- unlist(by(tmp_dta$"1",tmp_dta[[main]],cumsum)) n <- dim(.dta)[1] subcol=rep(rgb(0,0,0),n); for(i in 1:n){ t1 = col2rgb(tmp_dta$col[i])/256 subcol[i]=rgb(t1[1],t1[2],t1[3],1/(1+u[i])) } return(subcol); } ### Then get the plot is fairly easy: # INPUT data browsers <- structure(list(browser = structure(c(3L, 3L, 3L, 3L, 2L, 2L, 2L, 1L, 5L, 5L, 4L), .Label = c("Chrome", "Firefox", "MSIE","Opera", "Safari"),class = "factor"), version = structure(c(5L,6L, 7L, 8L, 2L, 3L, 4L, 1L, 10L, 11L, 9L), .Label = c("Chrome 10.0", "Firefox 3.5", "Firefox 3.6", "Firefox 4.0", "MSIE 6.0", "MSIE 7.0","MSIE 8.0", "MSIE 9.0", "Opera 11.x", "Safari 4.0", "Safari 5.0"), class = "factor"), share = c(10.85, 7.35, 33.06, 2.81, 1.58,13.12, 5.43, 9.91, 1.42, 4.55, 1.65), ymax = c(10.85, 18.2, 51.26,54.07, 55.65, 68.77, 74.2, 84.11, 85.53, 90.08, 91.73), ymin = c(0,10.85, 18.2, 51.26, 54.07, 55.65, 68.77, 74.2, 84.11, 85.53,90.08)), .Names = c("browser", "version", "share", "ymax", "ymin"), row.names = c(NA, -11L), class = "data.frame") ## data clean browsers=browsers[order(browsers$browser,browsers$share),] arr=aggregate(share~browser,browsers,sum) ### choose your cols mainCol = c('chartreuse3', 'chocolate3','deepskyblue3','gold3','deeppink3') donuts_plot(browsers$share,rep(1,11),browsers$version, cols=subcolors(browsers,"browser",mainCol), legend=F,pilabels = T,borderlit = rep(F,4) ) donuts_plot(arr$share,rep(1,5),arr$browser, cols=mainCol,pilabels=F,legend=T,legend_offset=-.02, outradius = .71,radius = .0,innerradius=.0,add=T, borderlit = rep(F,4) ) ###end of line :如果使用string_concat(),我会将指针的地址传递给必须为realloc() - ed的字符串,但返回重新分配的字符串本身。所以我会避免指向可能标记为realloc的位置的返回值。如果realloc返回NULL,则函数返回指向原始字符串的指针。

free

char* string_concat(char** x, char* y) {
  size_t len_x = strlen(*x);
  size_t len_y = strlen(y);
  char *temp = realloc(*x, len_x + len_y + 1);
  if(!temp) return *x;     //or do some more appropriate error handling
  memcpy(temp+len_x, y, len_y+1);
  *x = temp;
  return *x;
}

很好地解释了here