我写这段代码, repeatc for repeat char to char array。 它有效。
重复重复字符串N次到字符串数组。 但重复字符串到字符串数组核心转储。
A, A, A,
AB, AB, AB,
*** Error in `./untitled': free(): invalid pointer: 0x0000000000400f3d ***
....
....
Aborted (core dumped)
为什么呢? 我的代码:
// --cc =' gcc'
[indent=4]
init
var carray = repeatc ('A', 3)
for i in carray do stdout.printf ("%c, ", i)
// A, A, A
stdout.putc ('\n')
var sarray = repeats ("AB", 3)
for i in sarray do stdout.printf ("%s, ", i)
stdout.putc ('\n')
def repeatc (e: char, n: int): array of char
var a = new array of char[n]
Memory.copy (a, &e, sizeof (char))
Memory.copy (&a[1], a, sizeof (char) * (n - 1)) // gcc
return a
def repeats (e: string, n: int): array of string
var a = new array of string[n]
// WORKS: for var i = 0 to (n - 1) do a[i] = e
// Memory.copy HOW TO?
// (CORE DUMPED)
Memory.copy (a, &e, sizeof (uint8*))
Memory.copy (&a[1], a, sizeof (uint8*) * (n - 1))
return a
为什么此代码核心转储? 以及如何解决它?
答案 0 :(得分:2)
此代码有几个问题。
[indent=4]
init
var carray = repeatc ('A', 3)
for i in carray do stdout.printf ("%c, ", i)
// A, A, A
实际上,它打印了A,A,A," (注意尾随的逗号和空格)。有很多方法可以解决这个问题,最简单的方法就是做stdout.puts (string.joinv (", ", sarray))
。
def repeatc (e: char, n: int): array of char
var a = new array of char[n]
Memory.copy (a, &e, sizeof (char))
使用Memory.copy(C中的a.k.a. memcpy)复制单个字节实在是太愚蠢了。绝对没有理由不在这里做a[0] = e
。它更容易,而且表现更好。
Memory.copy (&a[1], a, sizeof (char) * (n - 1)) // gcc
这是非常错误的。您告诉它将sizeof (char) * (n - 1)
个字节从a
位置复制到a
之后的1个字节。这与你想要的非常不同,它是用数组中第一个字节的值填充a的其余部分。实际上你不应该使用Memory.copy
,你应该使用Memory.set
:Memory.set (a, e, n)
可以替换那些Memory.copy
行。
那就是说,你真正想要的是一个字符串而不是一系列字符。如果是这种情况,您可以替换整个功能,只需拨打string.nfill (3, 'A')
。
def repeats (e: string, n: int): array of string
var a = new array of string[n]
// WORKS: for var i = 0 to (n - 1) do a[i] = e
// Memory.copy HOW TO?
你还需要一个循环。一旦您开始尝试使用Memory.*
函数,您正在使用指针,因此您需要了解内存的布局方式。字符串实际上只是字符数组,而数组只是指向数组中第一个元素的指针。当你创建一个字符串数组时,你所拥有的是一个指向指针的指针(在C中,gchar**
),而不是指向一个大的连续块的指针,你可以开始将你的字符数据复制到。
我猜您尝试使用Memory.copy
代替循环和简单分配来提高性能;对于性能而言,唯一真正糟糕的事情就是简单的赋值将调用g_strdup
来调用strlen
,因此您最终会扫描输入字符串N次以计算长度而不是一次。你能得到的最好的东西可能是:
var elen = e.length
for var i = 0 to (n - 1)
a[i] = (string) Memory.dup (e, (uint) elen);
如果您真的关心性能,那么您需要做的是返回一个无主字符串数组,这些字符串都指向内存中的相同位置。或者,如果你感兴趣的是真正的连接字符串而不是数组,那就做一些像
这样的事情。def repeatwithsep (e: string, n: int, separator: string): string
var elen = e.length;
var slen = separator.length;
var a = new StringBuilder.sized ((elen * n) + (slen * (n - 1)) + 1);
for var i = 0 to (n - 1)
if i != 0
a.append_len (separator, slen)
a.append_len (e, elen)
return (owned) a.str;