Saya ingin tahu berapa banyak RAM yang saya gunakan dalam proyek saya, sejauh yang saya tahu, tidak ada cara untuk benar-benar menyelesaikannya (selain melalui dan menghitung sendiri). Saya telah sampai pada tahap dalam proyek yang agak besar di mana saya telah menentukan bahwa saya kehabisan RAM.
Saya telah menentukan ini karena saya dapat menambahkan satu bagian dan kemudian semua kacau di tempat lain dalam kode saya tanpa alasan yang jelas. Jika saya melakukan #ifndef
sesuatu yang lain, itu akan berhasil lagi. Tidak ada yang salah secara pemrograman dengan kode baru.
Saya menduga untuk sementara waktu bahwa saya sampai pada akhir RAM yang tersedia. Saya tidak berpikir saya menggunakan terlalu banyak tumpukan (walaupun itu mungkin), apa cara terbaik untuk menentukan berapa banyak RAM yang sebenarnya saya gunakan?
Melewati dan mencoba menyelesaikannya, saya memiliki masalah ketika saya mendapatkan enum dan struct; berapa memori yang biayanya?
edit pertama : JUGA, saya telah mengedit sketsa saya begitu banyak sejak mulai, ini bukan hasil sebenarnya yang saya dapatkan pada awalnya, tetapi itu adalah apa yang saya dapatkan sekarang.
text data bss dec hex filename
17554 844 449 18847 499f HA15_20140317w.cpp.elf
16316 694 409 17419 440b HA15_20140317w.cpp.elf
17346 790 426 18562 4882 HA15_20140317w.cpp.elf
Baris pertama (dengan teks 17554) tidak berfungsi, setelah banyak pengeditan, baris kedua (dengan teks 16316) berfungsi sebagaimana mestinya.
sunting: baris ketiga memiliki semuanya berfungsi, membaca serial, fungsi baru saya, dll. Saya pada dasarnya menghapus beberapa variabel global dan kode duplikat. Saya menyebutkan ini karena (seperti yang diduga) ini bukan tentang kode ini per sae, itu harus tentang penggunaan RAM. Yang membawa saya kembali ke pertanyaan awal, "bagaimana cara mengukurnya" Saya masih memeriksa beberapa jawaban, terima kasih.
Bagaimana cara saya menafsirkan informasi di atas?
Sejauh ini pemahaman saya adalah:
`TEXT` is program instruction memory
`DATA` is variables (unitialised?) in program memory
`BSS` is variables occupying RAM
karena BSS jauh lebih kecil dari 1024 byte, mengapa yang kedua bekerja, tetapi yang pertama tidak? Jika itu DATA+BSS
maka keduanya menempati lebih dari 1024.
sunting kembali: Saya mengedit pertanyaan untuk memasukkan kode, tetapi sekarang saya telah menghapusnya karena itu benar-benar tidak ada hubungannya dengan masalah (selain praktik pengkodean yang mungkin buruk, deklarasi variabel dan sejenisnya). Anda dapat meninjau kode dengan melihat kembali melalui pengeditan jika Anda benar - benar ingin melihatnya. Saya ingin kembali ke pertanyaan yang ada, yang lebih didasarkan pada: Bagaimana mengukur penggunaan RAM.
String
ketik di program Anda? Hal ini diketahui sering melakukan alokasi dan pelepasan memori dinamis, yang dapat memecah tumpukan hingga ke titik di mana Anda mungkin tidak memiliki memo lagi.String
s karena overhead. Saya senang bekerja dengan array char, yang mengatakan, saya hampir selalu mendefinisikan semua array char saya dengan ukuran tetap (saat ini, saya memiliki satu byte array yang tidak murni karena saya mengubah panjang konten untuk kompilasi ulang yang berbeda.Jawaban:
Anda dapat menggunakan fungsi yang disediakan AVRGCC: Memonitor Penggunaan Stack
Fungsi ini dimaksudkan untuk memeriksa penggunaan tumpukan tetapi yang dilaporkan adalah RAM aktual yang belum pernah digunakan (selama eksekusi). Ia melakukannya dengan "mengecat" (mengisi) RAM dengan nilai yang diketahui (0xC5), dan kemudian memeriksa area RAM dengan menghitung berapa byte yang masih memiliki nilai awal yang sama.
Laporan tersebut akan menampilkan RAM yang belum pernah digunakan (RAM gratis minimum) dan karenanya Anda dapat menghitung RAM maks yang telah digunakan (Total RAM - RAM yang dilaporkan).
Ada dua fungsi:
StackPaint dijalankan secara otomatis selama inisialisasi dan "mengecat" RAM dengan nilai 0xC5 (dapat diubah jika diperlukan).
StackCount dapat dipanggil kapan saja untuk menghitung RAM yang belum digunakan.
Berikut ini adalah contoh penggunaannya. Tidak berbuat banyak tetapi dimaksudkan untuk menunjukkan cara menggunakan fungsi.
sumber
Masalah utama yang dapat Anda miliki dengan penggunaan memori saat runtime adalah:
malloc
ataunew
)Keduanya sebenarnya sama dengan AVR SRAM (2K pada Arduino) digunakan untuk keduanya (selain data statis yang ukurannya tidak pernah berubah selama eksekusi program).
Secara umum, alokasi memori dinamis jarang digunakan pada MCU, hanya beberapa perpustakaan yang biasanya menggunakannya (salah satunya adalah
String
kelas, yang Anda sebutkan tidak digunakan, dan itu bagus).Tumpukan dan tumpukan dapat dilihat pada gambar di bawah ini (milik Adafruit ):
Oleh karena itu, masalah yang paling diharapkan datang dari stack overflow (yaitu ketika stack tumbuh menuju heap dan overflow di atasnya, dan kemudian -jika heap tidak digunakan sama sekali- meluap di zona data statis SRAM. Pada saat itu, Anda memiliki risiko tinggi:
Untuk mengetahui jumlah memori yang tersisa antara bagian atas tumpukan dan bagian atas tumpukan (sebenarnya, kami dapat menyebutnya bagian bawah jika kami mewakili tumpukan dan tumpukan pada gambar yang sama seperti yang digambarkan di bawah), Anda dapat menggunakan fungsi berikut:
Dalam kode di atas,
__brkval
menunjuk ke atas tumpukan tetapi0
ketika tumpukan belum digunakan, dalam hal ini kita menggunakan&__heap_start
menunjuk ke mana__heap_start
, variabel pertama yang menandai bagian bawah tumpukan;&v
menunjuk ke bagian atas tumpukan (ini adalah variabel terakhir yang didorong pada tumpukan), maka rumus di atas mengembalikan jumlah memori yang tersedia untuk tumpukan (atau tumpukan jika Anda menggunakannya) untuk tumbuh.Anda dapat menggunakan fungsi ini di berbagai lokasi kode Anda untuk mencoba dan mencari tahu di mana ukuran ini semakin berkurang.
Tentu saja, jika Anda melihat fungsi ini mengembalikan angka negatif maka sudah terlambat: Anda sudah terlalu banyak menumpuk!
sumber
malloc
dannew
satu-satunya cara saya bisa melakukan itu? Jika demikian, maka saya tidak punya apa-apa yang dinamis. Juga, saya baru tahu bahwa UNO memiliki 2K SRAM. Saya pikir itu 1K. Mempertimbangkan ini, saya tidak kehabisan RAM! Saya perlu mencari di tempat lain.calloc
. Tetapi Anda mungkin menggunakan lib pihak ke-3 yang menggunakan alokasi dinamis tanpa Anda sadari (Anda harus memeriksa kode sumber dari semua dependensi Anda untuk memastikannya)Ketika Anda mencari cara untuk menemukan file .elf yang dihasilkan di direktori sementara Anda, Anda dapat menjalankan perintah di bawah ini untuk membuang penggunaan SRAM, di mana
project.elf
harus diganti dengan.elf
file yang dihasilkan . Keuntungan dari output ini adalah kemampuan untuk memeriksa bagaimana SRAM Anda digunakan. Apakah semua variabel harus bersifat global, apakah semuanya benar-benar diperlukan?Perhatikan bahwa ini tidak menunjukkan tumpukan atau penggunaan memori dinamis seperti yang dicatat Ignacio Vazquez-Abrams dalam komentar di bawah.
Selain itu a
avr-objdump -S -j .data project.elf
dapat diperiksa, tetapi tidak ada program saya yang menghasilkan sesuatu dengan itu jadi saya tidak bisa memastikan apakah itu berguna. Ini seharusnya ke daftar 'diinisialisasi (non-nol) Data'.sumber
avr-size
. Tapi itu tidak akan menunjukkan alokasi dinamis atau menumpuk penggunaan.avr-objdump
danavr-size
dan saya akan segera mengedit posting saya di atas. Terima kasih untuk ini.Akan lebih baik menggunakan kombinasi estimasi manual dan dengan menggunakan
sizeof
operator. Jika semua deklarasi Anda statis, maka ini akan memberi Anda gambaran yang akurat.Jika Anda menggunakan alokasi dinamis, maka Anda mungkin mengalami masalah setelah Anda mulai deallocating memori. Ini karena fragmentasi memori pada heap.
Enum membutuhkan ruang sebanyak
int
. Jadi, jika Anda memiliki 10 elemen dalamenum
deklarasi, itu akan menjadi10*sizeof(int)
. Juga, setiap variabel yang menggunakan enumerasi hanyalah sebuahint
.Untuk struktur, akan lebih mudah digunakan
sizeof
untuk mengetahuinya. Struktur menempati ruang (minimum) sama dengan jumlah anggotanya. Jika kompiler melakukan perataan struktur, maka mungkin lebih, namun ini tidak mungkin dalam kasusavr-gcc
.sumber
sizeof
untuk menggunakan untuk tujuan ini. Saat ini, saya sudah memiliki hampir 400 byte (secara global). Sekarang saya akan memeriksa dan menghitung enum (secara manual) dan struct (yang saya punya beberapa — dan saya akan gunakansizeof
), dan melaporkan kembali.sizeof
mengetahui ukuran data statis Anda karena ini akan dicetak oleh avrdude IIRC.Ada sebuah program bernama Arduino Builder yang menyediakan visualisasi rapi jumlah flash, SRAM, dan EEPROM yang digunakan oleh program Anda.
Builder Arduino membentuk bagian dari solusi IDE CodeBlocks Arduino . Ini dapat digunakan sebagai program mandiri atau melalui IDE CodeBlocks Arduino.
Sayangnya Arduino Builder agak lama tetapi harus bekerja untuk sebagian besar program dan sebagian besar Arduino, seperti Uno.
sumber