Thanks!!
The next challenge is live:
http://ubuntuforums.org/showthread.php?t=1500005
Good Luck!!!
Thanks!!
The next challenge is live:
http://ubuntuforums.org/showthread.php?t=1500005
Good Luck!!!
Last edited by texaswriter; June 2nd, 2010 at 08:25 PM. Reason: added next challenge
In case this is helpful to anyone: I found out the source of my elusive "bug". It is not really a bug in any sense... Like I had said, I ran my program through Valgrind and it detected *nothing*. But running the following code: export MALLOC_CHECK_=0
before you execute a program that crashes with an error similar to this: glibc detected export double free or corruption (top):
will solve that problem.
That's good news.... I really don't understand why it would be a problem... I have thoroughly checked my free() statements... It very specifically checks to see if it is null before freeing...
Anyways... I hope that the above is useful to somebody.
If you have to set MALLOC_CHECK_ your memory management is messed up.
You are allocating and reallocating the storage array in blocks of malloc_step without setting the internal values to NULL so when you get to the freeing you end up calling free on memory that was never allocated in the first place yet you have at your disposal variable 'i' containing the exact number of elements in use and could have used it to good effect in your free loop.
The directory_path variable is similarly afflicted and uses a scheme so similar that the mechanism ought to have been abstracted out to avoid repetition. See the code below which is suitable for reuse in other programs. Usage should be obvious.
Untested.
Code:#include <stdio.h> #include <stdlib.h> #include <string.h> struct char_vec { char **data; /* data[0], data[1], ..., data[elements - 1] */ size_t elements; /* exact number of elements */ size_t block_size; /* number of elements in an allocation unit */ }; struct char_vec *char_vec_new(size_t block_size) { struct char_vec *s; if (!(s = malloc(sizeof (struct char_vec)))) { printf("malloc failure\n"); exit(5); } if (!(s->data = malloc(block_size * sizeof *s->data))) { printf("malloc failure\n"); exit(5); } s->elements = 0; s->block_size = block_size; s->data[0] = NULL; return s; } void char_vec_free(struct char_vec *s) { char **dp = s->data; size_t e = s->elements; while (e--) free(*dp++); free(s->data); s->data = NULL; /* Future calls to grow or free will segfault. */ free(s); } void char_vec_grow(struct char_vec *s, const char *new_data) { /* The extra space is for the NULL terminator. */ size_t blocks = (s->elements + 1) / s->block_size + 1; size_t needed = (s->elements + 2) / s->block_size + 1; if (needed > blocks) { s->data = realloc(s->data, needed * s->block_size * sizeof *s->data); if (!s->data) { printf("malloc failure\n"); exit(5); } } s->data[s->elements++] = strdup(new_data); s->data[s->elements] = NULL; }
Last edited by StephenF; July 2nd, 2010 at 06:32 PM.
Thanks for that. I'll check it out and see if I can fix that in the original program. Otherwise, I'll keep those subroutines in mind.
Im on it
May the source be with you...! 8)
Written in Ruby language:
PHP Code:
# Warning! Not precise implementation due to my coding ability.
require 'optparse'
require 'ostruct'
require 'etc'
=begin
The purpose of this class is to parse command line arguments.
=end
class CommandLineParser
# Parse all command line arguments.
#
def self.parse(args)
options = OpenStruct.new
# Columns is a -C (not implemented) flag. It's default flag.
options.columns = false
# Long is a -l or --long flag.
options.long = false
# All is an -a or --all flag.
options.all = false
# Classify is a -F or --classify flag.
options.classify = false
# Human readable is a -h or --human-readable flag.
options.readable = false
# The very arguments handling.
opts = OptionParser.new do |opts|
opts.banner = "List directory contents.\n"\
"Usage: ./ls.rb [OPTIONS]... [FILE]..."
opts.separator ""
opts.on("-l", "--long", "Use a long listing format.") do |long|
options.long = long
end
opts.on("-a", "--all", "Do not ignore entries starting with '.'.") do |all|
options.all = all
end
opts.on("-F", "--classify",
"Append indicator (one of */=>@|) to entries.") do |classify|
options.classify = classify
end
opts.on("-h", "--human-readable",
"With -l, print sizes in human readable format",
"(e.g., 1K 234M 2G).") do |readable|
options.readable = readable
end
# Default path
options.path = "."
opts.on_tail("-p", "--path PATH", String,
"Set the directory to show it contents") do |path|
options.path = path
end
end
# Parse command line arguments.
opts.parse!(args)
# If no arguments given (when every option is equal to 'false'),
# use -C flag as a default.
options.columns = true unless options.marshal_dump.values.include?(true)
# Return Hash object as a result of parsing.
options.marshal_dump
end
end
=begin
Ruby implementation of Linux console utility 'ls'.
=end
class Ls
def list
with_option = CommandLineParser.parse(ARGV)
out = []
Dir.entries(with_option[:path]).sort.each do |file|
# Default option handling (when no arguments provided).
next if file.start_with?(".") and with_option[:columns]
# Change working directory.
Dir.chdir(with_option[:path])
if File.directory?(file) and with_option[:classify]
next if file.start_with?(".") and not with_option[:all]
file.concat("/")
end
if with_option[:long]
next if file.start_with?(".") unless with_option[:all]
# Container of long notation string.
long = []
# File's permissions.
permissions = sprintf("%o", File.stat(file).mode)
long << permissions
# Quantity of hard links to a file.
nlink = File.stat(file).nlink
long << nlink
# Owner of a file.
uid = File.stat(file).uid
owner = Etc.getpwuid(uid).name
long << owner
# An owner's group.
group = File.stat(file).gid
long << group
# File's size.
size = File.size(file)
size = to_k(size) if with_option[:readable]
long << size
# The last time, when file was accessed by someone.
ctime = File.ctime(file)
long << ctime.strftime("%b %e")
# Filename.
file = long << file
# Actual string to output.
file = file.join(" ")
end
out << file
end
puts out
nil
end
private
def to_k(bytes)
Float(bytes / 1024).to_s + "K"
end
end
print Ls.new.list
Bookmarks