0

このコード、repeat char から char 配列への繰り返しを記述します。できます。

文字列配列に対して繰り返し文字列を 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

このコードがコア ダンプされたのはなぜですか? とそれを修正する方法?

4

1 に答える 1

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 では memcpy とも呼ばれます) を使用して 1 バイトをコピーするのは、ばかげています。ここでやらない理由はまったくありませんa[0] = e。その方が簡単で、パフォーマンスが向上します。

    Memory.copy (&a[1], a, sizeof (char) * (n - 1)) // gcc

これは非常に間違っています。sizeof (char) * (n - 1)バイトをその場所aから 1 バイト後にコピーするように指示していますa。これは、配列の最初のバイトの値で 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.*、ポインターを操作するため、メモリがどのように配置されているかを理解する必要があります。文字列は実際には単なる文字の配列であり、配列は配列の最初の要素への単なるポインターです。文字列の配列を作成すると、gchar**文字データのコピーを開始できる大きな連続ブロックへのポインターではなく、ポインターへのポインター (C では、) になります。

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;
于 2015-07-12T21:43:25.983 に答える